docs(CLAUDE.md): add code style section aligned with glyphdiff conventions

This commit is contained in:
Ilia Mashkov
2026-03-06 23:03:45 +03:00
commit e2eba5ec55
44 changed files with 3686 additions and 0 deletions

20
.dockerignore Normal file
View File

@@ -0,0 +1,20 @@
node_modules
.svelte-kit
build
dist
.env
.env.*
!.env.example
.git
.gitignore
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.DS_Store
Thumbs.db
.vscode
.idea
*.swp
*.swo
*~

27
.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
node_modules
# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
# Git worktrees
.worktrees

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
engine-strict=true

3
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["svelte.svelte-vscode"]
}

666
AGENT.md Normal file
View File

@@ -0,0 +1,666 @@
# AGENT.md
## Available MCP Tools
You have access to **five powerful MCP tool sets** for comprehensive research and analysis:
### 1. CodeGraphContext (CGC) - Local Code Analysis
**Purpose**: Analyze, understand, and navigate local codebases through graph-based relationships.
**When to Use**:
- Working with existing code in the local repository
- Understanding how code works together
- Finding where functions/classes are defined or used
- Analyzing the impact of code changes
- Identifying dead code or complex code
- Tracing execution flows across files
- Refactoring or maintaining code
**Key Tools**:
- `codegraph_find_code` - Find functions, classes, or code by keywords
- `codegraph_analyze_code_relationships` - Analyze callers, callees, inheritance, dependencies
- `codegraph_watch_directory` - Monitor active projects for real-time updates
- `codegraph_add_code_to_graph` - Index code into the graph
- `codegraph_find_dead_code` - Find potentially unused functions
- `codegraph_calculate_cyclomatic_complexity` - Measure function complexity
- `codegraph_get_repository_stats` - Understand codebase size and structure
- `codegraph_list_indexed_repositories` - Check what code is available
**Common Queries**:
- "Where is the `process_payment` function?"
- "What functions call `get_user_by_id`?"
- "If I change `calculate_tax`, what code will be affected?"
- "Show me the call chain from `main` to `process_data`"
- "Find dead or unused code in this project"
- "What's the most complex function in this codebase?"
**Best Practices**:
- Check `codegraph_list_indexed_repositories` first to see what code is available
- Use `codegraph_watch_directory` for projects you're actively working on
- Start with `codegraph_find_code` for simple searches
- Use `codegraph_analyze_code_relationships` for deep analysis and impact assessment
- Check `codegraph_list_watched_paths` to see what's being monitored
- Background indexing jobs return a `job_id` - use `codegraph_check_job_status` to track progress
---
### 2. Context7 - Up-to-Date Library Documentation
**Purpose**: Get current, version-specific documentation and code examples for thousands of libraries and frameworks.
**When to Use**:
- Needing up-to-date documentation for libraries or frameworks
- Looking for code examples and best practices
- Implementing new features using external libraries
- Learning APIs you haven't used before
- Wanting to avoid hallucinated APIs or outdated code
- Working with specific versions of libraries
**Key Tools**:
- `context7_resolve-library-id` - Find the correct library ID (max 3 calls/question)
- `context7_query-docs` - Get documentation for a library (max 3 calls/question)
**Usage Pattern**:
1. Call `context7_resolve-library-id` with library name and your task
2. Review results, select best match based on description, trust score, benchmark score
3. Call `context7_query-docs` with the library ID and your specific question
**If user provides library ID in `/org/project` format**, you can skip step 1.
**Common Queries**:
- "How do I set up authentication with Supabase?"
- "Show me examples of using Next.js middleware"
- "How to implement JWT auth with Express.js"
- "What's the best way to handle errors in React hooks?"
**Best Practices**:
- **ALWAYS use `context7_resolve-library-id` first** unless user provides exact library ID
- **Be specific** in your query: "How to set up authentication with JWT" not "auth"
- **Max 3 calls**: Do not call these tools more than 3 times per question
- **Check scores**: Prioritize libraries with higher trust and benchmark scores
- **No secrets**: Never include API keys, passwords, credentials, or personal data in queries
- **Explain choice**: Briefly explain which library was selected when multiple matches exist
---
### 3. Brave - Quick Web Search
**Purpose**: Quick web searches for current information.
**When to Use**:
- Needing fast, general web searches
- Looking for recent news or updates
- Finding current technology information
- Quick research without deep crawling
**Key Tools**:
- `brave_brave_web_search` - General web search
- `brave_brave_local_search` - Local business/places search
---
### 4. Tavily - Advanced Search & Extraction
**Purpose**: Comprehensive web search with advanced capabilities including content extraction and crawling.
**When to Use**:
- Needing in-depth research on technical topics
- Extracting content from multiple URLs
- Crawling entire websites for documentation
- Finding detailed implementation examples
**Key Tools**:
- `tavily_tavily_search` - Advanced search with detailed results
- `tavily_tavily_extract` - Extract structured content from URLs
- `tavily_tavily_crawl` - Crawl websites systematically
- `tavily_tavily_map` - Map website structure
---
### 5. BrightData - Web Scraping & Data Extraction
**Purpose**: Comprehensive web scraping, structured data extraction, and browser automation.
**When to Use**:
- Web scraping with anti-bot bypass
- Structured data extraction (clean markdown, tables, embedded content)
- Browser automation for complex, interactive websites
- Testing web applications
**Key Tools**:
- `brightData_search_engine` - Web search using Google Search API
- `brightData_scrape_as_markdown` - Extract and convert to markdown
- `brightData_search_engine_batch` - Multi-query searches
- Playwright browser automation (11 tools)
---
## Project Context
**Project Name**: allmywork
**Purpose**: Portfolio web application
**Stack**: SvelteKit, Bun, Biome, Tailwind CSS, Feature Sliced Design (FSD)
**Deployment**: Self-hosted on VPS in Docker container
---
## Bun Usage Guidelines
**Always use `bun` commands, never `npm`**:
- **Package management**: `bun install`, `bun add`, `bun remove`
- **Script execution**: `bun run <script-name>`
- **Running binaries**: Use `bunx <package>` instead of `npx <package>`
- **Test runner**: `bun test` or `bun run test` (Vitest via Bun)
**Examples**:
```bash
# Install dependencies
bun install
# Add dependency
bun add -D tailwindcss
# Run script
bun run dev
# Run binary (instead of npx)
bunx @biomejs/biome init
# Run tests (Vitest via Bun)
bun run test
```
---
## Agent Roles & Responsibilities
### UI/UX Agent
**Responsibilities**:
- Design and implement UI components using Svelte 5 features (runes, snippets)
- Apply Tailwind CSS classes following the mixed approach pattern:
- Use utilities directly for one-off styles
- Create component classes for repeated patterns
- Ensure responsive design and accessibility (WCAG compliance)
- Implement micro-interactions and animations
- Work within Feature Sliced Design structure
**Naming Conventions**:
- Components: PascalCase (e.g., `UserProfile.svelte`)
- Utilities: camelCase (e.g., `formatDate.ts`)
**Comment Style**:
```svelte
/**
* Component description
*/
<script lang="ts">
// Short remark for inline logic
</script>
```
**When to Use**:
- "Design/create component", "Add styling", "UI implementation", "Add animations"
---
### Feature Developer Agent
**Responsibilities**:
- Create and manage FSD slices (pages, features, entities, widgets, shared)
- Implement business logic and data flows
- Integrate UI components with backend functionality
- Follow FSD methodology for slice composition
- Ensure proper separation of concerns across layers
**FSD Structure**:
```
src/
├── pages/ # Full pages
├── features/ # User interactions
├── entities/ # Business entities
├── widgets/ # Composed components
├── shared/ # Shared code
└── app/ # SvelteKit app layer (routes)
```
**When to Use**:
- "Create feature", "Implement business logic", "Add page", "Create slice"
---
### Test Engineer Agent
**Responsibilities**:
- Write unit tests using Vitest
- Write E2E tests using Playwright
- Test critical user flows
- Ensure test coverage meets quality standards
- Follow test-driven approach for new features
**Testing Infrastructure**:
- Unit tests: Vitest (Vite-native)
- E2E tests: Playwright
- Target coverage: 80%+ for new code
- Write tests alongside implementation (TDD for new features)
**When to Use**:
- "Write tests", "Test coverage", "Add E2E test", "Test flow"
---
### Documentation Agent
**Responsibilities**:
- Write inline code comments following "Less is more" principle
- Create API documentation
- Write README files and guides
- Document FSD structure and slice usage
- Explain core logic and caveats succinctly
**Comment Patterns**:
```typescript
/**
* Function description explaining core logic
*/
export function processPayment(data: PaymentData): Promise<Payment> {
// Validate input data
const validated = validateData(data);
// Process payment with fallback
return processWithFallback(validated);
}
```
**When to Use**:
- "Write documentation", "Add comments", "Document API", "Create README"
---
### Architecture Reviewer Agent
**Responsibilities**:
- Review code for FSD compliance
- Identify architectural violations and anti-patterns
- Ensure proper layer separation
- Check for circular dependencies
- Verify component and slice integration patterns
**Review Checklist**:
- [ ] FSD layer boundaries respected
- [ ] No circular dependencies
- [ ] Proper slice composition
- [ ] Shared code appropriately extracted
- [ ] Feature isolation maintained
**When to Use**:
- "Review architecture", "Check FSD compliance", "Analyze code structure"
---
## Key Workflows
### 1. Creating a New Feature
**Prerequisites**: None required
**Steps**:
1. **Create feature branch**:
```bash
git checkout -b feature/featureName
```
2. **Plan FSD slice**:
- Determine which layers needed (page, feature, entity, widget, shared)
- Identify dependencies between layers
- Plan data flow
3. **Implement entities** (bottom-up):
```bash
# Example: src/entities/user/ui/UserAvatar.svelte
# Example: src/entities/user/model/types.ts
```
4. **Implement features**:
```bash
# Example: src/features/auth/ui/LoginForm.svelte
# Example: src/features/auth/model/useAuth.ts
```
5. **Compose widgets** (if needed):
```bash
# Example: src/widgets/header/ui/Header.svelte
```
6. **Create page**:
```bash
# Example: src/pages/home/ui/HomePage.svelte
# Example: src/pages/home/index.ts
```
7. **Integrate in app routes**:
```bash
# src/app/routes/+page.svelte
import { HomePage } from '$lib/pages/home';
```
8. **Write tests**:
- Unit tests for business logic
- E2E tests for critical flows
9. **Commit with conventional format**:
```bash
git commit -m "feat(featureName): short yet capacitive description"
```
**Output**: Complete feature implementation with FSD-compliant structure
**Success Criteria**:
- Feature works as specified
- All tests pass
- FSD layer boundaries respected
- Code follows naming conventions
- Comments explain core logic
---
### 2. Creating a New Component
**Prerequisites**: None required
**Steps**:
1. **Identify layer**:
- Entity: Reusable business entity component
- Feature: User interaction component
- Widget: Composed UI component
- Page: Full page component
2. **Create component file**:
```bash
# src/features/myFeature/ui/MyComponent.svelte
```
3. **Write Svelte 5 component**:
```svelte
<script lang="ts">
/**
* Component description
*/
let { data }: { data: DataType } = $props();
// Reactive state with runes
let state = $state({});
</script>
<div class="tailwind-classes">
<!-- Component content -->
</div>
```
4. **Add Tailwind styles**:
- One-off styles: Use utilities directly
- Repeated patterns: Extract to shared classes
5. **Export from index** (if applicable):
```typescript
// src/features/myFeature/index.ts
export { MyComponent } from './ui/MyComponent.svelte';
```
6. **Write tests**:
```typescript
// src/features/myFeature/ui/MyComponent.test.ts
```
7. **Commit**:
```bash
git commit -m "feat(myFeature): add MyComponent for ..."
```
**Output**: Working component with tests
**Success Criteria**:
- Component renders correctly
- Follows naming conventions
- Has appropriate tests
- Styles follow Tailwind pattern
---
### 3. Running Tests
**Prerequisites**: Project initialized with Vitest and Playwright
**Steps**:
1. **Run unit tests**:
```bash
bun run test
# or
bun run test:watch
```
2. **Run E2E tests**:
```bash
bun run test:e2e
```
3. **Run all tests**:
```bash
bun run test:all
```
4. **Check coverage**:
```bash
bun run test:coverage
```
**Output**: Test results with pass/fail status
**Success Criteria**:
- All tests pass
- Coverage meets 80%+ for new code
- No flaky tests
---
### 4. Building for Production
**Prerequisites**: Development complete, tests passing
**Steps**:
1. **Run linting and formatting**:
```bash
bun run lint
bun run format:check
```
2. **Build application**:
```bash
bun run build
```
3. **Test build locally**:
```bash
bun run preview
```
4. **Build Docker image**:
```bash
docker build -t allmywork:latest .
```
5. **Test Docker container**:
```bash
docker run -p 3000:3000 allmywork:latest
```
**Output**: Production-ready build and Docker image
**Success Criteria**:
- Build completes without errors
- Linting passes
- Docker image runs successfully
- Application accessible at expected port
---
### 5. Deploying to VPS
**Prerequisites**: Docker image built, VPS accessible
**Steps**:
1. **Transfer image to VPS**:
```bash
docker save allmywork:latest | gzip | ssh user@vps "docker load"
```
2. **Or build directly on VPS**:
```bash
ssh user@vps "cd /path/to/project && bun run build && docker build -t allmywork:latest ."
```
3. **Stop old container** (if exists):
```bash
ssh user@vps "docker stop allmywork && docker rm allmywork"
```
4. **Run new container**:
```bash
ssh user@vps "docker run -d --name allmywork -p 3000:3000 --restart unless-stopped allmywork:latest"
```
5. **Verify deployment**:
```bash
curl https://your-domain.com
```
**Output**: Running application on VPS
**Success Criteria**:
- Container running
- Application accessible
- No errors in logs
- HTTPS configured (if applicable)
---
## Code Conventions
### Naming
- **Components**: PascalCase (e.g., `UserProfile.svelte`)
- **Files/Functions**: camelCase (e.g., `formatDate.ts`, `getUserData`)
- **Types**: PascalCase (e.g., `UserData`, `PaymentResult`)
### Comments
**Multiline comments** (for documentation and types):
```typescript
/**
* Function description explaining core logic and caveats
*/
```
**One-line comments** (for short remarks):
```typescript
// Validate input before processing
```
**Rule**: "Less is more" - short yet capacitive, explaining core logic and caveats
### Commit Messages
**Format**: `prefix(featureName/fileName): short yet capacitive one-line description`
**Prefixes**:
- `feat` - New feature
- `fix` - Bug fix
- `chore` - Maintenance tasks
- `refactor` - Code refactoring
- `docs` - Documentation changes
- `style` - Code style changes
- `test` - Test changes
- `perf` - Performance improvements
- `ci` - CI/CD changes
- `build` - Build system changes
- `revert` - Revert previous commit
**Examples**:
- `feat(auth): add OAuth2 token refresh`
- `fix(payment): resolve memory leak in service`
- `docs(readme): update setup instructions`
---
## Tool Selection Decision Tree
```
Need help with code or libraries?
├─ LOCAL codebase analysis?
│ └─ YES → CodeGraphContext
│ ├─ Find something → codegraph_find_code
│ ├─ Understand relationships → codegraph_analyze_code_relationships
│ ├─ Check impact → find_callers, find_all_callers
│ └─ Code quality → find_dead_code, find_most_complex_functions
└─ EXTERNAL library/framework?
└─ YES → Context7
├─ Have exact ID? → context7_query-docs
└─ Need to find ID? → resolve-library-id → query-docs
Need web research?
├─ Quick search?
│ └─ YES → Brave
│ └─ brave_brave_web_search
├─ Advanced research/extraction?
│ └─ YES → Tavily
│ ├─ tavily_tavily_search
│ ├─ tavily_tavily_extract
│ └─ tavily_tavily_crawl
└─ Scraping/testing?
└─ YES → BrightData
├─ brightData_search_engine
├─ brightData_scrape_as_markdown
└─ Playwright tools
```
---
## Deployment Strategy
**Self-Hosted Docker Deployment**:
- Build: `bun run build`
- Docker image: `docker build -t allmywork:latest .`
- Run: `docker run -d -p 3000:3000 --restart unless-stopped allmywork:latest`
- Update: `docker stop && docker rm && docker run ...`
---
## Git Workflow
**Branching Strategy**:
- Feature branches: `feature/featureName`
- Bugfix branches: `fix/issueName`
- Main branches: `main`, `develop`
**Commit Process**:
1. Write code
2. Run tests: `bun run test:all`
3. Run lint: `bun run lint`
4. Stage files: `git add`
5. Commit: `git commit -m "prefix(feature): description"`
6. Push: `git push`
7. Create PR
**Use `skip orchestrator` when committing** to avoid extra agent overhead.

473
CLAUDE.md Normal file
View File

@@ -0,0 +1,473 @@
## Project Configuration
- **Language**: TypeScript
- **Package Manager**: Bun
- **Add-ons**: none
---
# CLAUDE.md
## Project Overview
**Name**: allmywork
**Purpose**: Portfolio web application
**Stack**: SvelteKit + Bun + Biome + Tailwind CSS + Feature Sliced Design (FSD)
**Deployment**: Self-hosted on VPS with Docker
---
## Bun Usage Guidelines
**Always use `bun` commands, never `npm`**:
- **Package management**: `bun install`, `bun add`, `bun remove`
- **Script execution**: `bun run <script-name>`
- **Running binaries**: Use `bunx <package>` instead of `npx <package>`
- **Test runner**: `bun test` or `bun run test` (Vitest via Bun)
**Examples**:
```bash
# Install dependencies
bun install
# Add dependency
bun add -D tailwindcss
# Run script
bun run dev
# Run binary (instead of npx)
bunx @biomejs/biome init
# Run tests (Vitest via Bun)
bun run test
```
---
## Agent Fleet
Use the following agents for different tasks:
| Agent | When to Use |
|--------|-------------|
| `technical-architect` | Design architecture, API schemas, database design |
| `builder` | Write code, implement features, fix bugs, manage Git |
| `qa-reliability-engineer` | Test strategy, performance analysis, SLOs |
| `design-specialist` | UI/UX design, component design, styling |
| `knowledge-architect` | Documentation, research, explain concepts |
| `ops-engineer` | Deployment, CI/CD, infrastructure |
| `security` | Security review, vulnerability assessment |
| `workflow-orchestrator` | Multi-agent task coordination |
---
## Technology Stack
### Core Framework
- **SvelteKit**: Full-stack framework with file-based routing
- **Svelte 5**: Using runes (`$state`, `$derived`, `$effect`) and snippets
- **TypeScript**: Strict mode enabled
### Runtime & Build
- **Bun**: Package manager and runtime
- **Vite**: Build tool (included with SvelteKit)
### Code Quality
- **Biome**: Linting and formatting (ESLint/Prettier replacement)
- Configuration: Includes `.svelte` files in `files.includes`
### Styling
- **Tailwind CSS**: Utility-first CSS
- Integration: Via PostCSS with `vitePreprocess({ style: true })`
- Pattern: Mixed approach - utilities for one-off, classes for repeated patterns
### Architecture
- **Feature Sliced Design (FSD)**:
- `pages/` - Full pages
- `features/` - User interactions
- `entities/` - Business entities
- `widgets/` - Composed components
- `shared/` - Shared code
- `app/` - SvelteKit routes (configured via `svelte.config.ts`)
### Testing
- **Vitest**: Unit testing (Vite-native)
- **Playwright**: E2E testing
- Coverage target: 80%+ for new code
---
## Development Workflow
### 1. Start Development
```bash
# Install dependencies
bun install
# Start dev server
bun run dev -- --open
# Watch for changes
bun run dev
```
**Note**: Always use `bun` commands, never `npm`. For running binaries (like npx), use `bunx` instead.
### 2. Code Quality
```bash
# Lint code
bun run lint
# Format code
bun run format
# Check format without modifying
bun run format:check
# Fix all issues
bun run lint:fix && bun run format
```
### 3. Testing
```bash
# Run unit tests
bun run test
# Run E2E tests
bun run test:e2e
# Run all tests
bun run test:all
# Watch mode
bun run test:watch
# Coverage report
bun run test:coverage
```
### 4. Build & Deploy
```bash
# Build for production
bun run build
# Preview build
bun run preview
# Build Docker image
docker build -t allmywork:latest .
# Run Docker container
docker run -d -p 3000:3000 --restart unless-stopped allmywork:latest
```
---
## Code Conventions
### Naming
| Type | Convention | Example |
|------|------------|----------|
| Components | PascalCase | `UserProfile.svelte` |
| Functions/Files | camelCase | `formatDate.ts`, `getUserData` |
| Types/Interfaces | PascalCase | `UserData`, `PaymentResult` |
| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
### Comment Style
**Multiline** (for documentation and types):
```typescript
/**
* Process payment with retry logic
* Handles transient failures with exponential backoff
*/
```
**One-line** (for short remarks):
```typescript
// Validate input before processing
```
**Rule**: "Less is more" - short yet capacitive, explaining core logic and caveats
### Commit Messages
**Format**: `prefix(featureName/fileName): short yet capacitive one-line description`
**Prefixes**:
- `feat` - New feature introduced
- `fix` - Bug fix
- `chore` - Maintenance tasks (no code changes)
- `refactor` - Code refactoring (no functional change)
- `docs` - Documentation changes
- `style` - Code style changes
- `test` - Test additions/corrections
- `perf` - Performance improvements
- `ci` - CI/CD changes
- `build` - Build system changes
- `revert` - Revert previous commit
**Examples**:
```
feat(auth): add OAuth2 token refresh flow
fix(payment): resolve memory leak in service
docs(readme): update deployment instructions
```
---
## FSD Structure
```
src/
├── pages/ # Full pages (top-level FSD layer)
│ ├── home/
│ │ ├── ui/
│ │ │ └── HomePage.svelte
│ │ └── index.ts
│ └── about/
├── features/ # User interactions
│ ├── auth/
│ │ ├── ui/
│ │ │ ├── LoginForm.svelte
│ │ │ └── RegisterForm.svelte
│ │ ├── model/
│ │ │ ├── useAuth.ts
│ │ │ └── types.ts
│ │ └── index.ts
│ └── contact/
├── entities/ # Business entities
│ ├── user/
│ │ ├── ui/
│ │ │ └── UserAvatar.svelte
│ │ ├── model/
│ │ │ └── types.ts
│ │ └── index.ts
│ └── project/
├── widgets/ # Composed UI components
│ ├── header/
│ │ ├── ui/
│ │ │ └── Header.svelte
│ │ └── index.ts
│ └── footer/
├── shared/ # Shared code
│ ├── ui/
│ │ ├── Button.svelte
│ │ └── Input.svelte
│ ├── config/
│ │ └── site.ts
│ └── lib/
│ └── api.ts
└── app/ # SvelteKit app layer
└── routes/
├── +layout.svelte
├── +page.svelte
└── about/
└── +page.svelte
```
### FSD Rules
- **Bottom-up composition**: entities → features → widgets → pages → app
- **Public API**: Each slice exports via `index.ts`
- **No upward dependencies**: Lower layers cannot import from higher layers
- **Shared**: Only use `shared/` for truly cross-cutting concerns
---
## Key Workflows
### Creating a Feature
1. Create feature branch: `git checkout -b feature/featureName`
2. Plan FSD slice structure (pages → features → entities)
3. Implement entities (bottom layer)
4. Implement features with business logic
5. Compose widgets (if needed)
6. Create page
7. Integrate in `app/routes/+page.svelte`
8. Write tests (unit + E2E)
9. Commit: `git commit -m "feat(feature): description"`
10. Create PR
### Running Tests Before Commit
```bash
# Always run before committing
bun run lint # Check code quality
bun run test:all # Run all tests
bun run format:check # Check formatting
# Fix issues
bun run lint:fix
bun run format
```
### Building for Deployment
1. Run tests: `bun run test:all`
2. Lint code: `bun run lint`
3. Build: `bun run build`
4. Build Docker image: `docker build -t allmywork:latest .`
5. Test Docker container: `docker run -p 3000:3000 allmywork:latest`
6. Deploy to VPS (see docs/deployment.md)
---
## Important Notes
### Svelte 5 Features
- Use runes for reactivity: `$state`, `$derived`, `$effect`
- Use snippets for reusable logic
- TypeScript strict mode enabled
### Biome Configuration
- Lints and formats `.svelte` files
- Initialize with `bunx @biomejs/biome init`
- Run `bun run lint` and `bun run format` before commits
- Configuration in `biome.json`
### Tailwind Usage
- Direct utilities: `class="p-4 bg-blue-500 text-white"` (one-off)
- Component classes: Repeated patterns extracted to shared components
- Design tokens in `tailwind.config.ts`
### Deployment
- Self-hosted on VPS with Docker
- No Vercel/Netlify integration
- Docker image contains full application
- Use `docker restart allmywork` for updates
### Git Workflow
- Feature branches with PRs
- Use `skip orchestrator` when committing
- Conventional commit format enforced
- Self-review before merging
---
## Documentation
**Project Docs**: `/docs/` folder contains detailed guides
- `docs/development.md` - Development workflow
- `docs/testing.md` - Testing strategy
- `docs/deployment.md` - Deployment procedures
- `docs/fsd.md` - FSD architecture guide
**External Resources**:
- SvelteKit: https://kit.svelte.dev/docs
- Svelte 5: https://svelte.dev/docs/runes
- Bun: https://bun.sh/docs
- Biome: https://biomejs.dev
- Tailwind: https://tailwindcss.com/docs
- FSD: https://feature-sliced.design
---
## Troubleshooting
### Build Issues
```bash
# Clear build cache
rm -rf .svelte-kit
rm -rf node_modules/.vite
# Rebuild
bun install
bun run build
```
### Biome Not Formatting Svelte Files
- Check `biome.json` includes `.svelte` in `files.includes`
- Ensure Biome extension is installed in VS Code
### Tailwind Classes Not Applying
- Check `src/app.css` includes Tailwind directives
- Verify `tailwind.config.ts` content paths include `src/**/*.{svelte,ts,js}`
- Ensure PostCSS is enabled in `svelte.config.ts`
### FSD Import Errors
- Check slice `index.ts` exports
- Verify no upward dependencies
- Ensure proper path aliases configured
---
## Getting Help
**For code implementation**: Use `builder` agent
**For architecture decisions**: Use `technical-architect` agent
**For testing issues**: Use `qa-reliability-engineer` agent
**For UI/UX design**: Use `design-specialist` agent
**For documentation**: Use `knowledge-architect` agent
**For deployment**: Use `ops-engineer` agent
**For security review**: Use `security` agent
**Multi-agent tasks**: Use `workflow-orchestrator` agent
---
## Code Style
### Formatting (Biome)
- Indent: tabs
- Quote style: double quotes for JS/TS, double quotes for Svelte attributes
- Line width: 120 characters
- Semicolons: always
- Trailing commas: all
### TypeScript
- Strict mode: on
- Prefer `interface` over `type` for object shapes
- Always type component props via an `interface Props { ... }` block
- Use `$props()` rune — never `export let`
- Use `$derived()` and `$effect()` — never Svelte 4 `$:` syntax
- Use `$state()` for all reactive primitives
### Component Conventions
- File name: PascalCase (`Button.svelte`, `ProjectCard.svelte`)
- Store files: camelCase with `.svelte.ts` suffix (`sidebarStore.svelte.ts`)
- Story files: `.stories.svelte` suffix (Storybook CSF with Svelte addon)
- Test files: `.test.ts` for unit, `.svelte.test.ts` for component tests
- Each slice exports a public API via `index.ts`
### Svelte 5 Patterns
```svelte
<script lang="ts">
import { cn } from '$shared/lib/cn';
import type { Snippet } from 'svelte';
import type { HTMLButtonAttributes } from 'svelte/elements';
interface Props extends HTMLButtonAttributes {
variant?: 'primary' | 'secondary';
children: Snippet;
class?: string;
}
let { variant = 'primary', children, class: className, ...rest }: Props = $props();
const classes = $derived(cn(baseStyles, variantStyles[variant], className));
</script>
<button class={classes} {...rest}>
{@render children()}
</button>
```
### Comments
- Multiline JSDoc (`/** ... */`) for exported functions and component description headers
- Single-line (`//`) for inline logic remarks
- Principle: "less is more" — explain the *why*, not the *what*
### Import Order (Biome organizeImports)
1. Svelte/SvelteKit built-ins (`svelte`, `$app/...`)
2. FSD layer aliases (`$shared/...`, `$entities/...`, etc.)
3. Relative imports (`./`, `../`)
### Commit Messages
Format: `prefix(scope): short description`
Prefixes: `feat`, `fix`, `chore`, `refactor`, `docs`, `style`, `test`, `perf`, `ci`, `build`, `revert`
Example: `feat(shared/ui): add Button component with brutalist variants`

31
Dockerfile Normal file
View File

@@ -0,0 +1,31 @@
FROM oven/bun:1-alpine AS base
WORKDIR /app
FROM base AS deps
COPY package.json package-lock.json* ./
RUN bun install --frozen-lockfile
FROM base AS builder
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN bun install --frozen-lockfile
RUN bun run build
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 bun
RUN adduser --system --uid 1001 bun
COPY --from=builder /app/package.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/build ./
USER bun
EXPOSE 3000
CMD ["bun", "run", "index.js"]

42
README.md Normal file
View File

@@ -0,0 +1,42 @@
# sv
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```sh
# create a new project
npx sv create my-app
```
To recreate this project with the same configuration:
```sh
# recreate this project
npx sv@0.12.4 create --template minimal --types ts --install npm .
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```sh
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```sh
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.

35
biome.json Normal file
View File

@@ -0,0 +1,35 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.5/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false,
"includes": ["*.svelte", "*.ts", "*.js", "*.json", "*.css"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

File diff suppressed because it is too large Load Diff

45
package.json Normal file
View File

@@ -0,0 +1,45 @@
{
"name": "allmywork",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "biome check .",
"format": "biome format --write .",
"format:check": "biome format .",
"lint:fix": "biome check --write .",
"test": "vitest",
"test:watch": "vitest --watch",
"test:e2e": "playwright test",
"test:all": "bun run test && bun run test:e2e",
"test:coverage": "vitest --coverage"
},
"devDependencies": {
"@biomejs/biome": "^2.4.5",
"@playwright/test": "^1.58.2",
"@sveltejs/adapter-auto": "^7.0.0",
"@sveltejs/kit": "^2.50.2",
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tailwindcss/postcss": "^4.2.1",
"@testing-library/svelte": "^5.3.1",
"@types/node": "^25.3.3",
"@vitest/coverage-v8": "^4.0.18",
"@vitest/ui": "^4.0.18",
"autoprefixer": "^10.4.27",
"jsdom": "^28.1.0",
"postcss": "^8.5.8",
"svelte": "^5.51.0",
"svelte-adapter-bun": "^1.0.1",
"svelte-check": "^4.4.2",
"tailwindcss": "^4.2.1",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vitest": "^4.0.18"
}
}

32
playwright.config.ts Normal file
View File

@@ -0,0 +1,32 @@
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./src/tests/e2e",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: "html",
use: {
baseURL: "http://localhost:4173",
trace: "on-first-retry",
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},
{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},
],
webServer: {
command: "npm run build && npm run preview",
port: 4173,
},
});

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
export default {
plugins: {
"@tailwindcss/postcss": {},
autoprefixer: {},
},
};

11
src/app.html Normal file
View File

@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import '../../app.css';
import favicon from '$lib/assets/favicon.svg';
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
</svelte:head>
{@render children()}

View File

@@ -0,0 +1,5 @@
<script lang="ts">
import { HomePage } from '$pages/home';
</script>
<HomePage />

1
src/app/styles/app.css Normal file
View File

@@ -0,0 +1 @@
@import "tailwindcss";

20
src/app/types/app.d.ts vendored Normal file
View File

@@ -0,0 +1,20 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
namespace svelte.JSX {
interface HTMLAttributes<T> {
class?: string;
title?: string;
}
}
}
export {};

2
src/entities/index.ts Normal file
View File

@@ -0,0 +1,2 @@
// Public API for entities layer
// Add exports here when entities are implemented

2
src/features/index.ts Normal file
View File

@@ -0,0 +1,2 @@
// Public API for features layer
// Add exports here when features are implemented

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

1
src/lib/index.ts Normal file
View File

@@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.

1
src/pages/home/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from './ui';

View File

@@ -0,0 +1,54 @@
<script lang="ts">
import { Button } from '$shared/ui';
import type { Snippet } from 'svelte';
interface Props {
children?: Snippet;
}
let { children }: Props = $props();
</script>
<section class="min-h-screen flex flex-col items-center justify-center bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 p-8">
<div class="max-w-4xl w-full space-y-8 text-center">
<h1 class="text-6xl font-bold text-white mb-4 tracking-tight">
Welcome to All My Work
</h1>
<p class="text-xl text-slate-300 mb-8 leading-relaxed">
A portfolio web application built with SvelteKit, Bun, and modern web technologies.
</p>
<div class="flex gap-4 justify-center flex-wrap">
<Button variant="primary" size="lg" onclick={() => alert('Button clicked!')}>
Get Started
</Button>
<Button variant="secondary" size="lg" onclick={() => alert('Secondary action!')}>
Learn More
</Button>
</div>
<div class="mt-16 grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-white/10 backdrop-blur-lg rounded-lg p-6 border border-white/20">
<h2 class="text-2xl font-semibold text-white mb-3">SvelteKit</h2>
<p class="text-slate-300">Modern full-stack framework with file-based routing</p>
</div>
<div class="bg-white/10 backdrop-blur-lg rounded-lg p-6 border border-white/20">
<h2 class="text-2xl font-semibold text-white mb-3">Bun</h2>
<p class="text-slate-300">Fast runtime and package manager for JavaScript</p>
</div>
<div class="bg-white/10 backdrop-blur-lg rounded-lg p-6 border border-white/20">
<h2 class="text-2xl font-semibold text-white mb-3">Tailwind CSS</h2>
<p class="text-slate-300">Utility-first CSS framework for rapid UI development</p>
</div>
</div>
</div>
{#if children}
<div class="mt-16">
{@render children()}
</div>
{/if}
</section>

View File

@@ -0,0 +1 @@
export { default as HomePage } from './HomePage.svelte';

1
src/pages/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from './home';

View File

@@ -0,0 +1 @@
export * from './site';

View File

@@ -0,0 +1,5 @@
export const site = {
name: 'allmywork',
description: 'Portfolio web application',
url: 'https://allmywork.localhost'
};

3
src/shared/index.ts Normal file
View File

@@ -0,0 +1,3 @@
export * from './ui';
export * from './config';
export * from './lib';

18
src/shared/lib/api.ts Normal file
View File

@@ -0,0 +1,18 @@
const API_BASE = import.meta.env.VITE_API_BASE || '/api';
export async function fetchApi(endpoint: string, options?: RequestInit) {
const url = `${API_BASE}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers
}
});
if (!response.ok) {
throw new Error(`API error: ${response.status} ${response.statusText}`);
}
return response.json();
}

1
src/shared/lib/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from './api';

View File

@@ -0,0 +1,40 @@
<script lang="ts">
interface Props {
type?: 'button' | 'submit' | 'reset';
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
onclick?: () => void;
children: any;
}
let {
type = 'button',
variant = 'primary',
size = 'md',
disabled = false,
onclick,
children
}: Props = $props();
const variants = {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
danger: 'bg-red-600 text-white hover:bg-red-700'
};
const sizes = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-6 py-3 text-lg'
};
</script>
<button
{type}
{disabled}
onclick={onclick}
class="rounded-md font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed {variants[variant]} {sizes[size]}"
>
{@render children()}
</button>

View File

@@ -0,0 +1,26 @@
<script lang="ts">
interface Props {
type?: 'text' | 'email' | 'password' | 'number';
placeholder?: string;
disabled?: boolean;
value?: string;
oninput?: (e: Event) => void;
}
let {
type = 'text',
placeholder = '',
disabled = false,
value = '',
oninput
}: Props = $props();
</script>
<input
{type}
{placeholder}
{disabled}
{value}
oninput={oninput}
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
/>

2
src/shared/ui/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export { default as Button } from './Button.svelte';
export { default as Input } from './Input.svelte';

11
src/tests/basic.test.ts Normal file
View File

@@ -0,0 +1,11 @@
import { describe, it, expect } from 'vitest';
describe('Basic tests', () => {
it('should add numbers correctly', () => {
expect(1 + 1).toBe(2);
});
it('should subtract numbers correctly', () => {
expect(5 - 3).toBe(2);
});
});

View File

@@ -0,0 +1,6 @@
import { test, expect } from '@playwright/test';
test('homepage loads correctly', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveTitle(/allmywork/);
});

6
src/tests/setup.ts Normal file
View File

@@ -0,0 +1,6 @@
import { expect, afterEach } from 'vitest';
import { cleanup } from '@testing-library/svelte';
afterEach(() => {
cleanup();
});

2
src/widgets/index.ts Normal file
View File

@@ -0,0 +1,2 @@
// Public API for widgets layer
// Add exports here when widgets are implemented

3
static/robots.txt Normal file
View File

@@ -0,0 +1,3 @@
# allow crawling everything by default
User-agent: *
Disallow:

27
svelte.config.js Normal file
View File

@@ -0,0 +1,27 @@
import path from "node:path";
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import adapter from "svelte-adapter-bun";
const config = {
extensions: [".svelte"],
preprocess: vitePreprocess({
style: true,
}),
kit: {
adapter: adapter(),
files: {
routes: "src/app/routes",
},
alias: {
$lib: path.resolve("src/lib"),
$shared: path.resolve("src/shared"),
$pages: path.resolve("src/pages"),
$features: path.resolve("src/features"),
$entities: path.resolve("src/entities"),
$widgets: path.resolve("src/widgets"),
"$/*": "./src/*",
},
},
};
export default config;

11
tailwind.config.ts Normal file
View File

@@ -0,0 +1,11 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: ["./src/**/*.{html,js,svelte,ts}"],
theme: {
extend: {},
},
plugins: [],
};
export default config;

20
tsconfig.json Normal file
View File

@@ -0,0 +1,20 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"rewriteRelativeImportExtensions": true,
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// To make changes to top-level options such as include and exclude, we recommend extending
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
}

12
vite.config.ts Normal file
View File

@@ -0,0 +1,12 @@
import path from "node:path";
import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [sveltekit()],
resolve: {
alias: {
$lib: path.resolve("./src/lib"),
},
},
});

24
vitest.config.ts Normal file
View File

@@ -0,0 +1,24 @@
import path from "node:path";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { defineConfig } from "vitest/config";
export default defineConfig({
plugins: [svelte({ hot: !process.env.VITEST })],
test: {
globals: true,
environment: "jsdom",
setupFiles: ["./src/tests/setup.ts"],
include: ["src/**/*.{test,spec}.{js,ts}"],
exclude: ["src/tests/e2e/**/*.{test,spec}.{js,ts}"],
},
resolve: {
alias: {
$lib: path.resolve("./src/lib"),
$shared: path.resolve("./src/shared"),
$pages: path.resolve("./src/pages"),
$features: path.resolve("./src/features"),
$entities: path.resolve("./src/entities"),
$widgets: path.resolve("./src/widgets"),
},
},
});