docs(CLAUDE.md): add code style section aligned with glyphdiff conventions
This commit is contained in:
20
.dockerignore
Normal file
20
.dockerignore
Normal 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
27
.gitignore
vendored
Normal 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
|
||||
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["svelte.svelte-vscode"]
|
||||
}
|
||||
666
AGENT.md
Normal file
666
AGENT.md
Normal 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
473
CLAUDE.md
Normal 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
31
Dockerfile
Normal 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
42
README.md
Normal 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
35
biome.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1975
docs/plans/2026-03-06-portfolio-foundation.md
Normal file
1975
docs/plans/2026-03-06-portfolio-foundation.md
Normal file
File diff suppressed because it is too large
Load Diff
45
package.json
Normal file
45
package.json
Normal 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
32
playwright.config.ts
Normal 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
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
11
src/app.html
Normal file
11
src/app.html
Normal 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>
|
||||
12
src/app/routes/+layout.svelte
Normal file
12
src/app/routes/+layout.svelte
Normal 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()}
|
||||
5
src/app/routes/+page.svelte
Normal file
5
src/app/routes/+page.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { HomePage } from '$pages/home';
|
||||
</script>
|
||||
|
||||
<HomePage />
|
||||
1
src/app/styles/app.css
Normal file
1
src/app/styles/app.css
Normal file
@@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
||||
20
src/app/types/app.d.ts
vendored
Normal file
20
src/app/types/app.d.ts
vendored
Normal 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
2
src/entities/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// Public API for entities layer
|
||||
// Add exports here when entities are implemented
|
||||
2
src/features/index.ts
Normal file
2
src/features/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// Public API for features layer
|
||||
// Add exports here when features are implemented
|
||||
1
src/lib/assets/favicon.svg
Normal file
1
src/lib/assets/favicon.svg
Normal 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
1
src/lib/index.ts
Normal 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
1
src/pages/home/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './ui';
|
||||
54
src/pages/home/ui/HomePage.svelte
Normal file
54
src/pages/home/ui/HomePage.svelte
Normal 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>
|
||||
1
src/pages/home/ui/index.ts
Normal file
1
src/pages/home/ui/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as HomePage } from './HomePage.svelte';
|
||||
1
src/pages/index.ts
Normal file
1
src/pages/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './home';
|
||||
1
src/shared/config/index.ts
Normal file
1
src/shared/config/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './site';
|
||||
5
src/shared/config/site.ts
Normal file
5
src/shared/config/site.ts
Normal 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
3
src/shared/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './ui';
|
||||
export * from './config';
|
||||
export * from './lib';
|
||||
18
src/shared/lib/api.ts
Normal file
18
src/shared/lib/api.ts
Normal 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
1
src/shared/lib/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './api';
|
||||
40
src/shared/ui/Button.svelte
Normal file
40
src/shared/ui/Button.svelte
Normal 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>
|
||||
26
src/shared/ui/Input.svelte
Normal file
26
src/shared/ui/Input.svelte
Normal 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
2
src/shared/ui/index.ts
Normal 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
11
src/tests/basic.test.ts
Normal 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);
|
||||
});
|
||||
});
|
||||
6
src/tests/e2e/homepage.spec.ts
Normal file
6
src/tests/e2e/homepage.spec.ts
Normal 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
6
src/tests/setup.ts
Normal 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
2
src/widgets/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// Public API for widgets layer
|
||||
// Add exports here when widgets are implemented
|
||||
3
static/robots.txt
Normal file
3
static/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# allow crawling everything by default
|
||||
User-agent: *
|
||||
Disallow:
|
||||
27
svelte.config.js
Normal file
27
svelte.config.js
Normal 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
11
tailwind.config.ts
Normal 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
20
tsconfig.json
Normal 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
12
vite.config.ts
Normal 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
24
vitest.config.ts
Normal 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"),
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user