Add comprehensive skill file for creating and editing high-quality Kener documentation with guidelines for:
- Documentation structure and organization
- Custom heading anchors for deep linking
- Markdown features and formatting
- Quality guidelines and best practices
- Avoiding content duplication with references
- Complete workflow and checklist
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: rajnandan1 <16224367+rajnandan1@users.noreply.github.com>
refactor: Modify alertToVariables function to streamline alert data handling
refactor: Change alert_id and alert_incident_id types in types.ts for consistency
refactor: Simplify alert notification templates to include incident URL and update variable types
docs: Update alerting templates documentation to reflect new variables and structure
refactor: Enhance webhook alert template to accommodate new incident URL handling
refactor: Adjust server API to utilize the latest monitor tag for testing alerts
- Create UserRecordDashboard interface to include password status.
- Update password reset API to validate password strength and set user as verified.
- Refactor invitation handling in the manage route to streamline user management.
- Introduce invitation acceptance flow with password creation and validation.
- Create email template for user invitations.
- Implement invitation verification logic to ensure token validity and user existence.
- Enhance user management UI to support invitation resending and account activation.
The API reference page was blank because spec.content expected a parsed
JSON object but received a JSON string. Added JSON.parse() to properly
parse the OpenAPI spec before passing it to @scalar/express-api-reference.
Fixes#532
- Set Russian as default locale in seedSiteData and i18n server configuration
- Replace MMMM with LLLL format for proper Russian month declension (nominative case)
- Update all date format strings across incident pages and controllers
- Add date range validation (2023 to current+12 months) with 404 error handling
- Implement conditional navigation buttons that hide at date boundaries
- Fix Russian month names display (октябрь instead of октября in titles)
- Add MIN_YEAR constant to prevent navigation before system launch
- Improve TypeScript compatibility and fix linter errors
This resolves Russian grammatical issues and prevents access to invalid date ranges
while maintaining proper localization and user experience.
Refactors the subscription status toggle to use a dedicated handler, ensuring correct behavior when toggling status for both new and existing triggers. Enhances user experience by automatically saving and reloading data when needed.
Adds support for toggling the subscription trigger's active/inactive status from the UI and updates backend/controller logic to allow dynamic status changes. Restricts editing of subscription event configuration and user subscriptions to when the trigger is active, improving admin control and preventing unintended changes when subscriptions are inactive.
Returns structured error messages from notification providers, updates API logic to surface errors to users, and enhances UI to display error or success states during trigger tests. Also adjusts monitor API request payload and corrects data range calculation.
Relates to improved reliability and user experience.
Introduces per-device configuration for maximum data range and selectable days on the homepage, allowing separate settings for desktop and mobile. Updates UI, server logic, and data model to support these options, and uses user agent detection to apply the correct configuration. Improves flexibility for data display across devices.
Relates to #105
Introduces a 'tz' parameter for specifying timezone in embed scripts and iframe URLs, improving localization for embedded monitors.
Updates documentation and refactors parameter handling to prioritize explicit timezone over browser-detected values.
Relates to improved internationalization and user experience.
Enhances subscription menu by showing a default icon when no image is available.
Replaces hardcoded verification code in email template with a variable.
Prevents background scrolling when subscription menu is open.
Removes redundant new subscriber response in API.
Removes unused documentation button from subscriptions page.
Adjusts checkbox styling for better UI consistency.
Introduces a unified function for monitoring data insertion,
adds support for group monitor status updates, and ensures
consistency by routing all monitoring data writes through the
new logic. Removes duplicated validation and streamlines
group monitor handling for improved reliability.
Relates to #123
Introduces an option to enable a site status banner summarizing the operational state of monitored systems. Calculates and displays aggregated status with a progress bar. Localizes banner messages in all supported languages.
Helps users quickly assess overall system health from the homepage.
- Updated monitorSheet.svelte to use raw JSON data for AllGamesList, replacing the previous import method.
- Refactored game retrieval logic in monitorSheet.svelte to utilize GetGameFromId function with the new AllGamesList structure.
- Modified monitorsAdd.svelte to parse AllGamesList from raw JSON, ensuring consistent data usage across components.
- Enhanced event pages (+page.svelte) with appropriate meta tags for better SEO, including titles and descriptions.
- Added a new all-games-list.json file containing comprehensive game data for improved functionality and maintainability.
- Updated subscriptions page to clarify SMTP setup instructions for users.
Integrates translation function into subscription and maintenance components,
localizing all user-facing strings. Expands translation resources for multiple languages
to cover newly localized phrases, improving accessibility and user experience for non-English users.
Unifies URLs for incident events by switching from singular to plural path segments and removes obsolete routes to streamline navigation. Introduces paginated incident fetching with filtering and sorting to improve performance and scalability. Updates UI components to reflect new paths and behaviors.
Relates to improved incident management and navigation.
Introduces a copy-to-clipboard button for incident links with animated feedback. Adds ability to hide accordion chevrons and refactors chevron and copy button styles. Updates incident URL generation and allows querying monitors by tag.
Relates to improved UX for incident management.
Introduces a queue-based system to send email notifications for incident events, including creation, updates, monitor changes, and comments. Fetches eligible subscribers dynamically and uses configurable templates for email delivery. Also updates the UI to improve the Preview button styling for better user experience.
- Implemented GenerateTokenWithExpiry function for JWT token generation with a specified expiry time.
- Added GetSubscriberByID function to retrieve subscriber details by ID.
- Updated CreateNewSubscription to accept subscriber ID directly.
- Introduced GetSubscribersPaginated for paginated retrieval of subscribers.
- Enhanced subscription trigger management with CreateSubscriptionTrigger and GetSubscriptionTriggerByEmail functions.
- Updated email_code.html to change expiration notice from 1 day to 5 minutes.
- Modified layout.server.js to include canSendEmail check for conditional rendering.
- Updated subscription page to display subscribers with pagination and subscription status management.
- Refactored subscription-related API endpoints for improved clarity and functionality.
- Added server-side logic for managing subscription triggers and email settings.
- Added functionality to create, update, and delete subscribers and their subscriptions in the controller and database implementation.
- Introduced new API endpoints for subscribing and unsubscribing users, including email verification and management of subscription preferences.
- Created a new Svelte component for managing subscriptions, allowing users to subscribe to updates and manage their preferences.
- Added email template for sending verification codes to subscribers.
- Implemented utility functions for generating random numbers and validating email addresses.
Sometimes, it's useful to modify data in the monitoring_data table, for example, in case of a false positive.
I'm adding a new button in the monitor list that opens a popup
allowing users to change the status of monitor data for a given time
range.
feat: modify analytics event naming convention for consistency
fix: adjust delete monitor confirmation form layout for better UX
style: refine positioning of monitor action buttons for improved alignment
refactor: streamline password validation imports in setup and forgot password routes
fix: remove unnecessary line breaks in layout server file
Implements badges for monitors, including status, uptime, and liveness, along with a dedicated management page.
Adds embed options for various platforms with customizable styles.
Implements role-based access control with admin, editor, and member roles.
Introduces a user management system with profiles, activation/deactivation, and password reset.
Adds an email authentication system with verification and password reset via email.
Includes an invitation system with token-based invitations and admin controls.
Improves performance, security, UI, and developer experience.
Updates package version to 3.2.5 and adds vite-plugin-package-version.
Removes libcap related code from Dockerfile.
Improves the incident display by adding time status information
such as "Starts in", "Started", and "Will last for".
Also fixes database directory write permissions on startup.
Also fixes#337
- Makes the monitor tags wrap on smaller screens.
- Validates webhook body.
- Adds user agent to webhook.
- Fixes Discord logo URL construction.
Issue #336
Implements the SQL monitor feature, allowing users to monitor database connections and queries.
Adds UI elements for configuring SQL monitor parameters, including connection string, query, and timeout.
Validates user inputs for SQL monitor configuration.
Improves date formatting by adding timezone support using `date-fns-tz`.
Allows users to switch between different timezones via a new UI toggle in the settings.
Updates dependencies and integrates timezone functionality into date formatting functions.
Refactors the monitor component for better data display and user interaction, including improved uptime calculations and a dropdown for selecting time ranges.
Enhances incident creation and handling by adding incident sources and refining incident filtering.
Addresses UI responsiveness on smaller screens.
Improves incident management by filtering out existing auto incidents when creating manual incidents.
Enhances cron job scheduling by removing and adding jobs dynamically based on active monitors and prevents duplicated incidents.
Also, ensures jobs get triggered in the correct order.
Simplified Docker tagging - in turn fixes broken `alpine` tag to correctly point to latest stable Alpine release. Changes include:
- No more type=ref,event=branch – because this workflow is only for releases & manual triggers on `main` branch.
- Ensures `alpine` tag is always created for Alpine variant builds.
- Ensures `latest` tag is always created for Debian builds.
- Ensures all semver-based tags work correctly for both variants.
Improves incident display and management by introducing configurable incident group views and enhancing comment rendering to support HTML content.
Solves the bug raised in #295 where server crashes when an incident is created from an alert
Refines SMTP email settings by adding TLS configuration and allowing username/password to be optional. #300 and #298
Also, fixes a bug where only home page was being filtered. Now all pages are filtered. #297
Adds job to check if any Dependabot PRs are open and if so, fail the Docker build (since we need to ensure OS packages exist and are in their correct versions when using pinned versions for security purposes).
Noticed multiple individuals commenting about insecure/privacy-unfriendly Lato webfont library being served via Google Fonts. I had formerly suggested replacing this with BunnyFonts and was happy to see that added as a placeholder, however, I also understand someone’s comment about this being loaded from an external resource.
This brings that webfont local. Size of webfont files should minimally grow Docker image sizes and I think we should prioritize UI and privacy by including it locally. The font’s licensing is OFL, so we are allowed to package it for distribution with this project.
I’m including both the full font family (for archival purposes) and Latin subset of this font. The Latin variant is used in the Docker image build (since this will apply to the majority of users and keep the Docker image smaller). If users need to extend this with their own subsets, they can always load those as a custom font. :)
Adds a NO_DATA status to handle cases where monitor data is unavailable.
Refactors data interpolation and aggregation logic for better accuracy and clarity.
Updates documentation links.
fixes#288
Updates the Kener version from 3.1.2 to 3.1.3.
Refactors the group query to use `havingRaw` for better compatibility across different database systems.
Adds database information to the bug report template.
Updates documentation to reflect the new directory structure.
The documentation now correctly references images in the `/documentation` directory.
Removes the `src/static/documentation` directory in the Dockerfile.
Not sure if we are wanting Dependabot to track Node.js packages, so for the time being, commenting this block out, but leaving for now w/ “TODO” to come back to at a later point.
Changed from trying to use artifacts and the GHA workflow failing to now using a simple `BUILD_VERSION` repository variable and automatically updating that when the `build-and-push-to-registries` workflow succeeds.
Other changes include:
* Added `workflow_run` trigger to `generate-readme.yml` so when that workflow recognizes the “Publish Docker Image to Registries” workflow runs and succeeds, it will automatically run the `generate-readme.yml` workflow (since a new Docker release will require Docker image variants table in README.md to have versioning updated)
* Generate major and major-minor versions from the `BUILD_VERSION` repository variable (more efficient than storing three separate variables from the `build-and-push-to-registries` workflow job)
Changes include:
* Moving README generation to separate workflow (so that it can be trigger to run when any changes to `README.template.md` are pushed to `main` branch or a PR is opened with changes to template file
* GitHub Actions do not have privileges via `GITHUB_TOKEN` to commit to protected branches, thus, we need to take another approach and utilize a personal access token (which you’ll need to generate @rajnandan1) and add to the repository secrets (to avoid exposing that credential).
* Changes `publish-images` workflow to run now only when a new GitHub Release is created. (This will help prevent excessive workflow runs on merges into `main`)…in other words, @rajnandan1, you can merge freely into `main` now without excessive GitHub Actions usage.
The following changes have been made:
* Ensured `package-lock.json` is up-to-date with latest dependencies from `package.json` - moved check to new workflow job and set as dependency for ‘build-and-push-to-registries’ job
* Updated branch-tagging for non-main branches (used when building Docker images)
* Restored pinned OS package versions in Dockerfile (for best-security)
* Restored “TODO” comments to Dockerfile (for tracking purposes and because I will revisit those items later this week)
* Added `—no-fund` tag to suppress npm package funding messages (helpful for CI/CD)
* Changed from `wget` to `curl` to resolve Debian package versioning issue between differing architectures (was one of the reasons causing the build to fail)
* As a part of the last comment, needed to then conditionalize container healthcheck logic
* Checked in newest `package-lock.json` file
* Fixed broken Docker badges in `README.template.md`
🔄 Automate README Generation via Mustache Templating
- Use Mustache to dynamically generate `README.md` from `README.template.md`.
- Populate README with environment variables (e.g., `KENER_BUILD_FULL_VERSION`).
- Prevent direct edits to `README.md` by enforcing updates via the template.
- Enhance GitHub Actions workflow to auto-generate and commit the README.
- Add GitHub Action workflow (`protect-readme.yml`) to prevent others from direct updates to `README.md` via PR.
I caught an issue where the README will only auto-update listed Docker versions the first time. Commenting out for now (in case this PR gets merged before I have time to fix this). Will revisit this and fix this week.
Integrating Dependabot into the workflow ensures automatic dependency updates, improving security, reducing technical debt, and keeping packages up to date with minimal manual effort. This helps prevent vulnerabilities and maintain code stability over time.
Dependabot will automatically monitor the project’s dependencies and open pull requests (PRs) to update them when new versions are released. Here’s how it works:
1. Scans for Outdated Dependencies – It checks project dependency files (e.g., package.json, Dockerfile, .env.build, etc.) for outdated versions.
2. Fetches Latest Versions – When a newer version of a dependency is available, Dependabot retrieves it and updates the dependency files accordingly.
3. Opens a Pull Request – It then creates a PR with the updated dependency, detailing the changes and linking to release notes, changelogs, or security advisories.
4. Runs CI/CD Tests – If we end up setting up continuous integration (CI) tests, the PR will trigger the tests to check for breaking changes.
5. Security Updates – Dependabot also detects vulnerable dependencies and creates PRs to update them to a secure version.
6. Auto-Merging (Optional) – We might consider this at a later point, but if configured, it can automatically merge PRs when updates pass all tests and meet the requirements.
Noticed when doing some cleanup, that you had two awesome tags, but they both point to different URLs/repos. I added back in the one I had inadvertently removed.
* Expanded upon existing Docker README section.
* Created table which will contains version placeholder variables that will be replaced by new GitHub workflow job: “update_readme”. Job automatically runs after new images have been built & pushed to container registries.
Default documentation link in main nav won’t work because /docs are not included in built Docker images (to keep image smaller). Instead, changing seed data to point to the docs homepage. :)
Switching from Google Fonts to Bunny Fonts CDN. Bunny Fonts is an open-source, privacy-first web font platform. It is fully GDPR compliant (Google is not) and can act as a drop-in replacement for Google Fonts.
Streamlined the GitHub `publishImage.yml` workflow with the following functionality:
* Handle both Alpine and Debian variants through matrix strategy
* Push to both Docker Hub and GitHub Container Registry
* Add comprehensive tagging strategy, handling both branches (aka release version, e.g. 1.0.0), semantic versions (major.minor and major), and latest versions (`latest` and `alpine`)
* Add security aspects (cosign signing, proper permissions)
* Add better caching and multi-platform build settings
With this revised workflow, the following Docker image variants will be built for every successful release. As an example, if the release version is “3.0.9”, then the following Docker image variants will be built:
Debian variants (default):
- `kener:3.0.9` (Semver of current release)
- `kener:latest` (Latest Debian release, ’latest’ label points to 3.0.9)
- `kener:3.0` (major.minor version, major.minor ‘3.0’ label points to 3.0.9)
- `kener:3` (major version, major ‘3’ label points to 3.0.9)
Alpine variants (smallest filesize):
- `kener:3.0.9-alpine` (Semver of current release)
- `kener:alpine` (Latest Alpine release, ‘alpine’ label points to 3.0.9)
- `kener:3.0-alpine` (major.minor version, major.minor ‘3.0-alpine’ label points to 3.0.9)
- `kener:3-alpine` (major version, major ‘3-alpine’ label points to 3.0.9)
* Switch to multi-stage build pattern for smaller image size
* Add support for both Alpine and Debian variants via build args
* Change default image base to `node:23-slim` instead of using `node:23` (no need for full Debian base present in `node:23` since now prioritization is given to production-ready builds)
* Improve caching with --mount for npm dependencies
* Separate build and runtime dependencies
* Remove unnecessary Node.js packages in final stage
* Fix permissions on uploads/database directories
* Add proper scoping for build arguments
* Set NODE_ENV=production for better performance
This change reduces the final image size and improves build caching while adding flexibility to choose between Alpine and Debian base images.
Original: ~1.2GB
New Alpine: ~350MB
New Debian: ~450MB
When building for production, various warnings are output which slows down production build.
The following changes were made:
- Suppress unused export properties (unused-export-let).
- Suppress conflicting Svelte resolve warnings (conflicting-svelte-resolve).
- Suppress empty chunk warnings (empty-chunk).
- Suppress unused module imports (module-unused-import).
- Keep other important warnings visible, so we’re still aware of potential issues.
Now, production build should be cleaner and faster! 🚀
- Added Russian language support by creating ru.json with translations for various terms and phrases.
- Updated locales.json to include Russian in the list of available languages.
description: Specialized skill for creating and editing high-quality Kener documentation. MUST be used whenever creating or editing documentation files in the src/routes/(docs)/docs/content/ directory or updating docs.json navigation.
---
# Documentation Writer
## Overview
This skill provides guidelines and best practices for creating high-quality, easy-to-follow documentation for Kener. Use this skill when creating new documentation or editing existing documentation files.
## Documentation Structure
### Content Location
All documentation files are located in:
```
src/routes/(docs)/docs/content/
```
### File Organization
```
content/
├── introduction.md # Top-level pages
├── configuration.md
├── monitors/ # Nested sections
│ ├── overview.md
│ ├── api.md
│ └── ping.md
├── alerting/
│ ├── overview.md
│ └── triggers.md
└── setup/
├── email-setup.md
└── database-setup.md
```
### Navigation Configuration
Navigation is controlled by `/src/routes/(docs)/docs.json`:
```json
{
"sidebar":[
{
"group":"Getting Started",
"collapsible":false,
"pages":[
{
"title":"Introduction",
"slug":"introduction"
}
]
}
]
}
```
**Important**: When creating new documentation files, you MUST also update `docs.json` to add navigation entries.
## Required Frontmatter
Every documentation file MUST begin with YAML frontmatter:
```markdown
---
title: Your Page Title
description: A clear, concise description of the page content (used for SEO and previews)
---
```
## Custom Heading Anchors
Use custom heading IDs for stable deep linking. This is CRITICAL for maintaining links even if heading text changes.
### Syntax
```markdown
## Section Title {#section-title}
```
### Best Practices
1.**Always include custom IDs** for all H2 and H3 headings
2. Use lowercase, kebab-case format
3. Keep IDs short but descriptive
4. IDs should be unique within the document
### Examples
```markdown
## How API Monitoring Works {#how-api-monitoring-works}
Use GitHub-flavored callout syntax for important information:
```markdown
> [!NOTE]
> Additional context or helpful information
> [!WARNING]
> Caution about potential issues
> [!TIP]
> Helpful tips for users
> [!IMPORTANT]
> Critical information users should know
```
### Code Blocks
Always specify the language for syntax highlighting:
````markdown
```javascript
// Your code here
```
```bash
# Shell commands
```
```json
{
"config": "value"
}
```
````
### Tables
Use tables for structured information:
```markdown
| Column 1 | Column 2 | Column 3 |
| :------- | :------- | :------- |
| Value 1 | Value 2 | Value 3 |
```
### Internal Links
Reference other documentation pages using absolute paths:
```markdown
See the [Email Setup](/docs/setup/email-setup) guide for details.
```
For section anchors:
```markdown
See [Configuration Options](/docs/monitors/api#configuration-options).
```
## Documentation Structure Template
Follow this structure for comprehensive documentation pages:
```markdown
---
title: Feature Name
description: Brief description of the feature
---
Brief introduction paragraph explaining what the feature is and why it matters.
## How It Works {#how-it-works}
Explain the basic workflow or concept.
## Configuration Options {#configuration-options}
Document all available configuration options using tables:
| Field | Type | Description | Default |
| :------- | :------- | :---------- | :------ |
| `option` | `string` | What it does | `value` |
## Examples {#examples}
Provide practical examples with clear explanations.
### 1. Basic Example {#basic-example}
Simple use case with minimal configuration.
### 2. Advanced Example {#advanced-example}
More complex use case demonstrating advanced features.
## Best Practices {#best-practices}
### Topic 1 {#best-practices-topic-1}
Practical advice for optimal usage.
## Troubleshooting {#troubleshooting}
### Common Issues {#common-issues}
| Issue | Possible Cause | Solution |
| :---- | :------------- | :------- |
| Problem | Why it happens | How to fix |
## Next Steps {#next-steps}
- [Related Documentation 1](/docs/path/to/doc1)
- [Related Documentation 2](/docs/path/to/doc2)
```
## Quality Guidelines
### Writing Style
1. **Be Clear and Concise**: Use simple language and short sentences
2. **Be Action-Oriented**: Focus on what users need to do
3. **Be Consistent**: Use the same terms throughout documentation
4. **Be Complete**: Don't assume prior knowledge
### Content Requirements
1. **Start with Context**: Explain why the feature exists
2. **Show Examples**: Always include practical examples
3. **Include Edge Cases**: Document common pitfalls
4. **Link Related Topics**: Help users navigate to related information
### Technical Writing
1. **Use Active Voice**: "Configure the monitor" not "The monitor should be configured"
2. **Use Present Tense**: "Kener sends notifications" not "Kener will send notifications"
3. **Be Specific**: Include exact values, paths, and commands
4. **Test All Code**: Ensure all code examples work
## Avoid Duplication
### Before Creating New Documentation
1. **Search Existing Docs**: Check if the topic is already covered
2. **Use References**: If content exists elsewhere, link to it instead of duplicating
3. **Extend Existing Docs**: Consider adding to an existing page rather than creating a new one
### When Content Overlaps
**Instead of duplicating**:
```markdown
## Email Configuration
To send emails, you need to configure SMTP settings:
- SMTP_HOST=smtp.example.com
- SMTP_PORT=587
...
```
**Use references**:
```markdown
## Email Configuration
Kener supports email notifications through SMTP or Resend. For detailed configuration instructions, see the [Email Setup](/docs/setup/email-setup) guide.
```
### When to Duplicate vs Reference
**Duplicate when**:
- The information is critical to understanding the current topic
- The content is very brief (1-2 sentences)
- The duplicate provides necessary context
**Reference when**:
- Detailed configuration steps exist elsewhere
- The topic is comprehensively covered in another document
- The information would make the current document too long
## Workflow
### Creating New Documentation
1. **Plan the Structure**: Outline sections before writing
2. **Check for Existing Content**: Ensure you're not duplicating
3. **Write the Content**: Follow the template and guidelines
4. **Add Custom Heading IDs**: Include `{#id}` for all major headings
5. **Update docs.json**: Add navigation entry
6. **Add Internal Links**: Link to related documentation
7. **Review and Test**: Verify all links, code examples, and formatting
### Editing Existing Documentation
1. **Read the Full Document**: Understand the existing content
2. **Maintain Consistency**: Match the existing style and tone
3. **Update Related Sections**: Keep all sections consistent
4. **Preserve Custom IDs**: Never change existing `{#custom-ids}`
5. **Update Links**: Ensure all internal references remain valid
### Before Finalizing
**Checklist**:
- [ ] Frontmatter includes title and description
- [ ] All H2 and H3 headings have custom IDs
- [ ] Code blocks specify language
- [ ] Tables are properly formatted
- [ ] Internal links use `/docs/` prefix
- [ ] Examples are practical and tested
- [ ] No duplicate content (or justified duplication)
- [ ] Navigation entry added to docs.json (for new pages)
- [ ] Related documentation is linked
## Common Patterns
### Configuration Documentation
Always document environment variables with tables:
description: CLI tools for Svelte 5 documentation lookup and code analysis. MUST be used whenever creating or editing any Svelte component (.svelte) or Svelte module (.svelte.ts/.svelte.js). If possible, this skill should be executed within the svelte-file-editor agent for optimal results.
---
# Svelte 5 Code Writer
## CLI Tools
You have access to `@sveltejs/mcp` CLI for Svelte-specific assistance. Use these commands via `npx`:
### List Documentation Sections
```bash
npx @sveltejs/mcp list-sections
```
Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths.
**Important:** When passing code with runes (`$state`, `$derived`, etc.) via the terminal, escape the `$` character as `\$` to prevent shell variable substitution.
## Workflow
1.**Uncertain about syntax?** Run `list-sections` then `get-documentation` for relevant topics
2.**Reviewing/debugging?** Run `svelte-autofixer` on the code to detect issues
3.**Always validate** - Run `svelte-autofixer` before finalizing any Svelte component
Thank you for considering contributing to our project! Here are some guidelines to help you get started.
---
## How to Contribute
1. Fork the repository and clone it locally.
2. Create a new branch for your feature or bug fix:
```bash
git checkout -b feature/your-feature-name
```
3. Make your changes and commit them:
```bash
git commit -m 'Describe your changes'
```
4. Push your changes to your fork:
```bash
git push origin feature/your-feature-name
```
5. Create a pull request to the `main` branch.
## Development
1. Install dependencies:
```bash
npm install
```
2. Create a `.env` file in the root of the project and add the following:
```bash
cp .env.example .env
```
2. Start the development server:
```bash
npm run dev
```
3. Open [http://localhost:3000](http://localhost:3000) in your browser.
## Documentation
The documentation is available in the `docs` folder. You can view it by going to [http://localhost:3000/docs/home](http://localhost:3000/docs/home) in your browser.
## Where to Start
1. Check out the [roadmap items](https://kener.ing/docs/roadmap/)
2. Add language support by following the [i18n guide](https://kener.ing/docs/i18n/)
Kener is an open-source status page application built with **SvelteKit 2.x** (**Svelte 5**) and **Node.js**, and is migrating to a **TypeScript-first** codebase. It provides real-time monitoring, uptime tracking, incident management, and customizable dashboards.
## Architecture
### Entry Points
- **`main.js`** - Production server entry: Express + SvelteKit handler + cron scheduler
- **`src/lib/server/startup.js`** - Cron job scheduler for monitors (runs every minute)
- Route data loading: `+page.server.ts` / `+layout.server.ts` (and client-side `+page.ts` / `+layout.ts` when needed)
- API endpoints: `+server.ts` files returning `json()`
## Types & Interfaces
Place types and interfaces in the appropriate folder based on where they are used:
- **`src/lib/types/`** - Shared types (safe to import from both server and client code). Use for domain models, DTOs, API response types, and anything needed on both sides.
- **`src/lib/server/types/`** - Server-only types. Use for DB models, internal service types, auth/session types, and anything that uses `$env/static/private` or Node-only APIs.
- **`src/lib/client/types/`** - Client-only types. Use for UI-specific types, component prop types, and anything that relies on browser/DOM APIs.
Always use `import type { ... }` when importing types to avoid accidental runtime imports.
# Check if VERSION is empty and set a fallback value
if [ -z "$VERSION" ]; then
VERSION=$(git tag -l --sort=-version:refname | grep -E '^(v)?[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1 || echo "3.1.0")
fi
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "Setting BUILD_VERSION to $VERSION"
gh variable set BUILD_VERSION --body "$VERSION"
env:
GH_TOKEN:${{ secrets.GH_PAT }} # Needs to be PAT w/ Read access to metadata and secrets & Read and Write access to actions, actions variables, and code
You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively:
## Available MCP Tools:
### 1. list-sections
Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths.
When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections.
### 2. get-documentation
Retrieves full documentation content for specific sections. Accepts single or multiple sections.
After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task.
### 3. svelte-autofixer
Analyzes Svelte code and returns issues and suggestions.
You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned.
### 4. playground-link
Generates a Svelte Playground link with the provided code.
After completing the code, ask the user if they want a playground link. Only call this tool after user confirmation and NEVER if code was written to files in their project.
Kener: An open-source Node.js status page application for real-time service monitoring, incident management, and customizable reporting. Simplify service outage tracking, enhance incident communication, and ensure a seamless user experience.
# sv
It uses files to store the data. Other adapters are coming soon
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
Visit a live server [here](https://kener.ing)
Read the documentation [here](https://kener.ing/docs)

## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```sh
# create a new project in the current directory
npx sv create
# create a new project in my-app
npx sv create my-app
```
## 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.
import{Casb,sasw,Vasm,Gasq,Nasx}from"./scheduler.b29f3093.js";consta=[];functionz(s,u){return{subscribe:A(s,u).subscribe}}functionA(s,u=b){lett;constr=newSet;functiono(n){if(w(s,n)&&(s=n,t)){consti=!a.length;for(consteofr)e[1](),a.push(e,s);if(i){for(lete=0;e<a.length;e+=2)a[e][0](a[e+1]);a.length=0}}}functionf(n){o(n(s))}functionl(n,i=b){conste=[n,i];returnr.add(e),r.size===1&&(t=u(o,f)||b),n(s),()=>{r.delete(e),r.size===0&&t&&(t(),t=null)}}return{set:o,update:f,subscribe:l}}functionC(s,u,t){constr=!Array.isArray(s),o=r?[s]:s;if(!o.every(Boolean))thrownewError("derived() expects stores as input, got a falsy value");constf=u.length<2;returnz(t,(l,n)=>{leti=!1;conste=[];letd=0,p=b;consty=()=>{if(d)return;p();constc=u(r?e[0]:e,l,n);f?l(c):p=x(c)?c:b},h=o.map((c,g)=>m(c,_=>{e[g]=_,d&=~(1<<g),i&&y()},()=>{d|=1<<g}));returni=!0,y(),function(){q(h),p(),i=!1}})}functionE(s){return{subscribe:s.subscribe.bind(s)}}export{Easa,Casd,zasr,Aasw};
import{wasu}from"./index.2f161581.js";varb;consty=((b=globalThis.__sveltekit_12t8kyc)==null?void0:b.base)??"";varh;(h=globalThis.__sveltekit_12t8kyc)==null||h.assets;constI="sveltekit:snapshot",x="sveltekit:scroll",O="sveltekit:index",c={tap:1,hover:2,viewport:3,eager:4,off:-1},k=location.origin;functionT(e){lett=e.baseURI;if(!t){consto=e.getElementsByTagName("base");t=o.length?o[0].href:e.URL}returnt}functionU(){return{x:pageXOffset,y:pageYOffset}}constd=newWeakSet,p={"preload-code":["","off","tap","hover","viewport","eager"],"preload-data":["","off","tap","hover"],keepfocus:["","true","off","false"],noscroll:["","true","off","false"],reload:["","true","off","false"],replacestate:["","true","off","false"]};functionf(e,t){consto=e.getAttribute(`data-sveltekit-${t}`);returnE(e,t,o),o}functionE(e,t,o){o!==null&&!d.has(e)&&!p[t].includes(o)&&(console.error(`Unexpected value for ${t} — should be one of ${p[t].map(s=>JSON.stringify(s)).join(", ")}`,e),d.add(e))}const_={...c,"":c.hover};functionv(e){lett=e.assignedSlot??e.parentNode;return(t==null?void0:t.nodeType)===11&&(t=t.host),t}functionN(e,t){for(;e&&e!==t;){if(e.nodeName.toUpperCase()==="A"&&e.hasAttribute("href"))returne;e=v(e)}}functionL(e,t){leto;try{o=newURL(einstanceofSVGAElement?e.href.baseVal:e.href,document.baseURI)}catch{}consts=einstanceofSVGAElement?e.target.baseVal:e.target,l=!o||!!s||A(o,t)||(e.getAttribute("rel")||"").split(/\s+/).includes("external"),r=(o==null?void0:o.origin)===k&&e.hasAttribute("download");return{url:o,external:l,target:s,download:r}}functionP(e){lett=null,o=null,s=null,l=null,r=null,a=null,n=e;for(;n&&n!==document.documentElement;)s===null&&(s=f(n,"preload-code")),l===null&&(l=f(n,"preload-data")),t===null&&(t=f(n,"keepfocus")),o===null&&(o=f(n,"noscroll")),r===null&&(r=f(n,"reload")),a===null&&(a=f(n,"replacestate")),n=v(n);functioni(w){switch(w){case"":case"true":return!0;case"off":case"false":return!1;default:returnnull}}return{preload_code:_[s??"off"],preload_data:_[l??"off"],keep_focus:i(t),noscroll:i(o),reload:i(r),replace_state:i(a)}}functiong(e){constt=u(e);leto=!0;functions(){o=!0,t.update(a=>a)}functionl(a){o=!1,t.set(a)}functionr(a){letn;returnt.subscribe(i=>{(n===void0||o&&i!==n)&&a(n=i)})}return{notify:s,set:l,subscribe:r}}functionS(){const{set:e,subscribe:t}=u(!1);return{subscribe:t,check:async()=>!1}}functionA(e,t){returne.origin!==k||!e.pathname.startsWith(t)}functionV(e){e.client}constY={url:g({}),page:g({}),navigating:u(null),updated:S()};export{OasI,casP,xasS,Iasa,Lasb,Pasc,Yasd,yase,Nasf,Tasg,Vash,Aasi,kaso,Uass};
import{sasB,AasO,BasR,gasb,lasg,casq,hasE,ias$,masw,dasA,kasS,Cask}from"../chunks/scheduler.b29f3093.js";import{SasD,iasH,dasy,vasN,easd,aasm,oasC,sasj}from"../chunks/index.7aebdd36.js";import{dasP}from"../chunks/singletons.222cc637.js";constz=()=>{constt=P;return{page:{subscribe:t.page.subscribe},navigating:{subscribe:t.navigating.subscribe},updated:t.updated}},_={subscribe(t){returnz().page.subscribe(t)}},x="node_modules/@sveltejs/kit/src/runtime/components/error.svelte";functionf(t){varh;lete,i=t[0].status+"",r,l,n,c=((h=t[0].error)==null?void0:h.message)+"",a;constv={c:function(){e=b("h1"),r=g(i),l=q(),n=b("p"),a=g(c),this.h()},l:function(s){e=E(s,"H1",{});varo=$(e);r=w(o,i),o.forEach(d),l=A(s),n=E(s,"P",{});varp=$(n);a=w(p,c),p.forEach(d),this.h()},h:function(){S(e,x,4,0,57),S(n,x,5,0,81)},m:function(s,o){m(s,e,o),C(e,r),m(s,l,o),m(s,n,o),C(n,a)},p:function(s,[o]){varp;o&1&&i!==(i=s[0].status+"")&&j(r,i),o&1&&c!==(c=((p=s[0].error)==null?void0:p.message)+"")&&j(a,c)},i:k,o:k,d:function(s){s&&(d(e),d(l),d(n))}};returny("SvelteRegisterBlock",{block:v,id:f.name,type:"component",source:"",ctx:t}),v}functionF(t,e,i){letr;O(_,"page"),R(t,_,a=>i(0,r=a));let{$$slots:l={},$$scope:n}=e;N("Error",l,[]);constc=[];returnObject.keys(e).forEach(a=>{!~c.indexOf(a)&&a.slice(0,2)!=="$$"&&a!=="slot"&&console.warn(`<Error> was created with unknown prop '${a}'`)}),t.$capture_state=()=>({page:_,$page:r}),[r]}letK=classextendsD{constructor(e){super(e),H(this,e,F,f,B,{}),y("SvelteRegisterComponent",{component:this,tagName:"Error",options:e,id:f.name})}};export{Kascomponent};
`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. Otherwise you may need to fix a <${name}>.`
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.