Thank you for your interest in contributing to Astro Loader Hashnode! This guide will help you get started with development, testing, and releasing.
- Development Setup
- Project Structure
- Development Workflow
- Testing
- Commit Conventions
- Release Process
- Code Style
- Pull Request Process
- Updating Schemas
- Node.js 20 or higher
- pnpm 9.0 or higher
- Git
-
Clone the repository:
git clone https://github.com/raisedadead/astro-loader-hashnode.git cd astro-loader-hashnode -
Install dependencies:
pnpm install
-
Set up environment variables (optional):
cp .env.example .env # Add your Hashnode token for testing with private content HASHNODE_TOKEN=your_token_here -
Run tests to ensure everything works:
pnpm run test
This is a monorepo with the following structure:
astro-loader-hashnode/
├── packages/
│ └── astro-loader-hashnode/ # Main package
│ ├── src/
│ │ ├── index.ts # Main entry point
│ │ ├── api/ # GraphQL client
│ │ ├── loaders/ # Content loaders
│ │ ├── queries/ # GraphQL queries
│ │ ├── types/ # TypeScript types
│ │ └── utils/ # Utility functions
│ └── tests/ # Test files
├── examples/
│ └── demo/ # Example Astro site
├── .github/workflows/ # CI/CD workflows
└── docs/ # Documentation
main- Production-ready code- Feature branches -
feature/descriptionorfeat/description - Bug fixes -
fix/descriptionorbugfix/description - Hotfixes -
hotfix/description
-
Create a feature branch:
git checkout -b feature/add-new-loader
-
Make your changes following the coding standards
-
Run the development checks:
# Lint your code pnpm run lint # Fix linting issues automatically pnpm run lint:fix # Run type checking pnpm run typecheck # Run tests pnpm run test # Run all checks together pnpm run check
-
Build the package:
pnpm run build
-
Test with the example:
cd examples/demo pnpm install pnpm run dev
From the root directory:
# Core development commands
pnpm run build # Build the package
pnpm run test # Run tests
pnpm run test:coverage # Run tests with coverage
pnpm run test:watch # Run tests in watch mode
pnpm run test:ui # Run tests with UI
pnpm run lint # Run linting
pnpm run lint:fix # Fix linting issues
pnpm run typecheck # Run type checking
pnpm run format # Format code
pnpm run format:check # Check formatting
pnpm run check # Run all checks (lint + typecheck + test)
pnpm run clean # Clean build artifacts
pnpm run audit # Check for security vulnerabilities
# Release commands
pnpm run release # Run semantic-releaseEnable debug logging in your test Astro config:
// astro.config.mjs
export default defineConfig({
vite: {
logLevel: 'info',
},
});# Run all tests
pnpm run test
# Run tests in watch mode
pnpm run test:watch
# Run tests with coverage
pnpm run test:coverage
# Run tests with UI
pnpm run test:ui- Tests are written using Vitest
- Place test files in the
tests/directory - Use descriptive test names
- Mock external dependencies (GraphQL API calls)
- Test both success and error scenarios
Example test structure:
import { describe, it, expect } from 'vitest';
import { hashnodeLoader } from '../src/index';
describe('hashnodeLoader', () => {
it('should create loader with correct configuration', () => {
// Test implementation
});
});We use Conventional Commits for consistent commit messages and automated versioning.
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
- feat - New features (minor version bump)
- fix - Bug fixes (patch version bump)
- perf - Performance improvements (patch version bump)
- docs - Documentation changes (no version bump)
- style - Code style changes (no version bump)
- refactor - Code refactoring (no version bump)
- test - Test changes (no version bump)
- chore - Build/tooling changes (no version bump)
- ci - CI/CD changes (no version bump)
For breaking changes, add ! after the type or include BREAKING CHANGE: in the footer:
# Either
git commit -m "feat!: redesign loader API"
# Or
git commit -m "feat: redesign loader API
BREAKING CHANGE: The configuration format has changed.
See migration guide for details."# Feature addition (minor release)
git commit -m "feat: add series loader support"
# Bug fix (patch release)
git commit -m "fix: resolve caching issue in GraphQL client"
# Performance improvement (patch release)
git commit -m "perf: optimize query batching"
# Documentation (no release)
git commit -m "docs: update API documentation"
# Breaking change (major release)
git commit -m "feat!: redesign loader configuration API"We use manual workflow-triggered releases with semantic-release for automation.
- Development happens on branches - no releases are triggered
- Merge to main - still no release
- Manual release trigger - releases are created manually via GitHub Actions
-
Ensure main branch is up to date and all changes are merged
-
Review changes since last release:
- Check recent commits and PRs merged to main
- Verify all intended changes are included
-
Trigger release via GitHub Actions:
- Go to GitHub Actions
- Select the "Release" workflow
- Click "Run workflow"
- Choose your options:
- Release type:
auto(recommended),patch,minor, ormajor - Dry run: Check this to preview the release without publishing
- Release type:
-
Version determination (when using
auto):- Semantic-release analyzes commits since last release:
- Patch:
fix,perfcommits - Minor:
featcommits - Major: commits with
!orBREAKING CHANGE
- Patch:
- Semantic-release analyzes commits since last release:
When you trigger the release workflow, GitHub Actions automatically:
- ✅ Runs all tests and quality checks
- ✅ Builds the package
- ✅ Determines version based on conventional commits
- ✅ Updates
package.jsonversion - ✅ Generates/updates
CHANGELOG.md - ✅ Publishes to npm
- ✅ Creates GitHub release with release notes
- ✅ Commits changes back to main
Before creating an actual release:
-
Run a dry-run first:
- Go to GitHub Actions → Release workflow
- Set "Dry run" to
true - Review the output to confirm expected version and changes
-
If satisfied, run the actual release:
- Run the workflow again with "Dry run" set to
false
- Run the workflow again with "Dry run" set to
# Set required environment variables
export GITHUB_TOKEN=your_github_token
export NPM_TOKEN=your_npm_token
# Run semantic-release locally
pnpm run release- Failed workflow: Check GitHub Actions logs for detailed error messages
- Wrong version: Ensure conventional commit format is followed
- Missing changes: Verify all intended commits are merged to main before triggering release
- Dry run errors: Fix issues before running actual release
The release workflow requires a GitHub App for authentication. This allows semantic-release to push changelog updates and version bumps back to the repository.
-
Go to GitHub Settings > Developer settings > GitHub Apps > New GitHub App (or visit: https://github.com/settings/apps/new)
-
Configure the app:
- App name: Choose a descriptive name (e.g.,
Releazer) - Homepage URL: Your repository or organization URL
- Webhook: Uncheck "Active" (not needed for this use case)
- App name: Choose a descriptive name (e.g.,
-
Set Repository permissions:
Permission Access Contents Read & Write Issues Read & Write Pull requests Read & Write Metadata Read-only (auto-granted) -
Under Where can this GitHub App be installed?, select based on your needs:
- "Only on this account" for personal use
- "Any account" if sharing across organizations
-
Click Create GitHub App
-
After creation, note the App ID displayed on the app's settings page
-
Scroll to Private keys section and click Generate a private key
- This downloads a
.pemfile - store it securely
- This downloads a
-
From your GitHub App's settings page, click Install App in the sidebar
-
Select the repository (or repositories) where you want to use it
-
Choose "Only select repositories" and pick the specific repos
Add these secrets to each repository using the app (Settings > Secrets and variables > Actions):
| Secret Name | Value |
|---|---|
RELEASE_APP_ID |
The App ID number from the app settings |
RELEASE_APP_PRIVATE_KEY |
The entire contents of the downloaded .pem file |
- Trigger the Release workflow with Dry run enabled
- Check the "Generate App Token" step succeeds
- If it fails, verify:
- The app is installed on the repository
- Both secrets are set correctly
- The private key includes the full PEM content (including
-----BEGIN/END-----lines)
We use Prettier for consistent code formatting:
# Format all files
pnpm run format
# Check formatting
pnpm run format:checkWe use ESLint for code quality:
# Lint code
pnpm run lint
# Fix linting issues
pnpm run lint:fix- Use strict TypeScript
- Export types from
src/types/index.ts - Use Zod for runtime validation
- Document complex types with JSDoc
When you add or modify fields returned by any loader:
- Update the relevant Zod schema under
packages/astro-loader-hashnode/src/types/schema.ts. - Update the corresponding transform function in the loader (e.g.
posts.tstransformHashnodePost). - Add or adjust tests asserting the new field appears in stored
dataand, if relevant, in therenderedoutput. - Update both READMEs (root and package) if the change is user-visible (new option, new field, or behavior change).
- Consider semantic versioning rules: new optional fields = minor, removed/changed fields = major.
- If adding digest-impacting fields, no extra steps are needed; the digest is calculated from the full data object.
- ✅ Run
pnpm run check- all checks must pass - ✅ Write tests for new features
- ✅ Update documentation if needed
- ✅ Use conventional commit messages
- ✅ Ensure your branch is up to date with main
- Title: Use conventional commit format
- Description:
- Explain what and why
- Link to related issues
- Include breaking changes if any
- Add screenshots for UI changes
- Automated checks must pass (CI, tests, linting)
- Code review by maintainers
- Approval required before merge
- Squash and merge to keep history clean
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix (non-breaking change)
- [ ] New feature (non-breaking change)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Documentation update
## Testing
- [ ] Tests pass locally
- [ ] Added tests for new functionality
- [ ] Updated documentation
## Checklist
- [ ] Code follows project style guidelines
- [ ] Self-review completed
- [ ] Commented code, particularly in hard-to-understand areas
- [ ] Changes generate no new warnings- Tests failing: Ensure all dependencies are installed with
pnpm install - Type errors: Run
pnpm run typecheckto see detailed type issues - Linting errors: Use
pnpm run lint:fixto auto-fix most issues - Build failures: Check that you're using Node.js 20+ and pnpm 9+
- Publication not found: Ensure your test
publicationHostis correct - API errors: Check your token validity for private content access
- Network failures: Cached content is used as fallback when API is unavailable
- Go to Hashnode Developer Settings
- Generate a new Personal Access Token
- Add it to your
.envfile asHASHNODE_TOKEN
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: For security issues only
Thank you for contributing! 🚀