Skip to content

Conversation

ImGajeed76
Copy link
Contributor

@ImGajeed76 ImGajeed76 commented May 17, 2025

PR TODO: Axonotes Website - Initial Structure & Content

This PR aims to set up the foundational pages and content outline for the Axonotes website.

Key Pages & Sections to Implement/Review:

  • Homepage (Landing Page):
    • Hero Section (Headline, Sub-headline, Visual, Primary CTA)
    • Problem/Pain Point ("Sound Familiar?")
    • Solution ("Introducing Axonotes")
    • Key Features Overview (3-5 core benefits)
    • "Your Voice is Crucial" - Feedback CTAs (Email & Survey)
    • Social/Community Links
  • Features Page ("Dive Deeper"):
    • Structure based on document sections (A-K)
    • Detail key functionalities for each section
  • Pricing & Access Page:
    • Outline Free Tier, Pro Plan (target price), Institutional Licenses
    • "Stay Informed" CTA
  • About Us / The Team Page:
    • Mission/Vision
    • Founders info
    • Call for community involvement
  • Community / Get Involved Page:
    • Centralize feedback channels (Email, Survey)
    • Links to GitHub & all social media
  • General Site Elements:
    • Consistent Navigation Bar (Header)
    • Comprehensive Footer (Copyright, Privacy/Terms placeholders, Socials, Contact)

Summary by CodeRabbit

  • New Features

    • Introduced a multilingual SvelteKit web application with English and German support and dynamic language switching.
    • Added landing, about, community, features, pricing, and legal pages with responsive design, interactive UI, and dark mode.
    • Implemented navigation bar, footer, theme toggle, and language switcher components.
    • Integrated GitHub-based feature request listing, pricing plans, and self-hosting promotion.
    • Added custom theming, typography, and comprehensive styling including Tailwind CSS and Skeleton UI.
  • Documentation

    • Added and refined README, imprint, privacy policy, and robots.txt for legal compliance and clarity.
  • Chores

    • Added configuration files for ESLint, Prettier, Tailwind CSS, npm, TypeScript, SvelteKit, Vite, and GitHub Actions workflows.
    • Included localization JSON files, environment variable templates, and Inlang project settings.
  • Style

    • Standardized formatting and list styles in documentation and config files.

Copy link

coderabbitai bot commented May 17, 2025

Walkthrough

This change establishes the foundational structure and configuration for a SvelteKit-based web application named AxonotesHomepage. It introduces internationalization (i18n) support, theming, project metadata, server hooks, ESLint and Prettier configurations, Tailwind CSS setup, GitHub workflows, and multiple Svelte components for pages, layouts, navigation, and UI elements. The project is prepared for multilingual content, accessibility, and modern development workflows.

Changes

Files / Groups Change Summary
.idea/..., .npmrc, .prettierignore, .prettierrc.json, .gitignore, .example.env, static/robots.txt Added IDE, formatting, environment, and version control configuration files; set up ignore patterns for Git and Prettier; provided robots.txt for web crawlers.
README.md Standardized list formatting, simplified badge section, and improved minor formatting for clarity.
eslint.config.js, tailwind.config.js, svelte.config.js, vite.config.ts, tsconfig.json Added and configured ESLint, Tailwind CSS, SvelteKit, Vite, and TypeScript settings for linting, styling, building, and type checking.
package.json Introduced project metadata, scripts, dependencies, devDependencies, and lint-staged configuration for a SvelteKit project with Tailwind, ESLint, Prettier, Husky, and other tooling.
axonotes-theme.css, src/app.css Added a custom CSS theme and global styles, including Tailwind, Skeleton UI, and custom checkbox styling with light/dark mode support.
messages/en.json, messages/de.json Added English and German localization files containing structured UI text for all app sections.
project.inlang/... Added Inlang project configuration, settings, and ignore rules for managing localization and i18n.
.github/workflows/ninja_i18n.yml Added a GitHub Actions workflow for i18n automation using the Ninja i18n action.
src/app.d.ts, src/lib/types/mdsvex.d.ts, src/lib/types/pricing.ts Added TypeScript declarations for app locals, .svx files, and pricing plan interfaces.
src/app.html Introduced the main HTML template with dynamic language, direction, and theming attributes.
src/hooks.server.ts, src/hooks.ts, src/lib/i18n.ts Added server and routing hooks for i18n integration using Paraglide-SvelteKit.
src/lib/devLog.ts Provided development-only logging utilities for debugging.
src/lib/components/FeatureList.svelte, LightSwitch.svelte, LanguageSwitcher.svelte, Navbar.svelte, PricingCard.svelte, SelfHostingSection.svelte Added reusable Svelte UI components for feature lists, theme switching, language selection, navigation, pricing cards, and self-hosting info.
src/lib/index.ts Added a placeholder for $lib imports.
src/lib/content/Imprint.svx, PrivacyPolicy.svx Added legal content pages for imprint and privacy policy as Svelte components.
src/routes/+layout.svelte, +error.svelte, +page.svelte Introduced main layout, error handling, and homepage components with i18n, analytics, navigation, and responsive design.
src/routes/about/+page.svelte, community/+page.svelte, features/+page.svelte, features/+page.server.ts, pricing/+page.svelte, legal/imprint/+page.svelte, legal/privacy-policy/+page.svelte Added Svelte page components for about, community, features (with server-side GitHub API integration and caching), pricing, and legal info, each with localized content and responsive UI.
src/routes/sitemap.xml/+server.ts Added a dynamic sitemap.xml generator for SEO, scanning all route pages.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant SvelteKit Server
    participant Paraglide i18n
    participant GitHub API
    participant NodeCache

    User->>Browser: Requests a page (e.g., /features)
    Browser->>SvelteKit Server: Sends HTTP request
    SvelteKit Server->>Paraglide i18n: Determines language context
    SvelteKit Server->>NodeCache: Checks for cached features data
    alt Cache hit and fresh
        NodeCache-->>SvelteKit Server: Returns cached features
    else Cache miss or stale
        SvelteKit Server->>GitHub API: Fetches issues with "feature" label (paginated)
        GitHub API-->>SvelteKit Server: Returns issues
        SvelteKit Server->>NodeCache: Stores features in cache
    end
    SvelteKit Server-->>Browser: Returns rendered page with localized content and features
    Browser->>User: Displays page with navigation, theming, and i18n
Loading

Possibly related PRs

  • Feat/initial page multilang #12: Introduces multilanguage support using Paraglide, adds localization JSON files, Inlang configuration, and integrates i18n in the app, including changes to server hooks and localization message files—directly related to the i18n setup in this PR.

Suggested reviewers

  • isvladu

Poem

(\(\
( -.-)
o_(")(")

A hop, a skip, a SvelteKit start,
With themes and languages, a work of art!
Pages, hooks, and configs align,
Features cached and docs divine.
Axonotes leaps into the light—
Multilingual, modern, and ever so bright!
🥕✨


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (4)
.gitignore (1)

1-24: Comprehensive .gitignore setup
The entries cover Node modules, OS files, build outputs, Vite timestamps, and environment files with selective un‐ignores. Consider also ignoring editor directories like .vscode/ if team members use VSCode, to prevent local settings from being committed.

src/routes/+page.svelte (1)

1-2: Add semantic structure and metadata.
The static markup is valid, but for improved accessibility, SEO, and semantics, wrap the content in a <main> tag and include a <svelte:head> block to set the page <title>.

Apply this diff:

--- src/routes/+page.svelte
+++ src/routes/+page.svelte
@@ -1,2 +1,11 @@
-<h1>Welcome to SvelteKit</h1>
-<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
+<svelte:head>
+  <title>Welcome to Axonotes</title>
+</svelte:head>
+
+<main>
+  <h1>Welcome to SvelteKit</h1>
+  <p>
+    Visit 
+    <a href="https://svelte.dev/docs/kit" target="_blank" rel="noopener noreferrer">
+      the SvelteKit docs
+    </a> to get started.
+  </p>
+</main>
.idea/AxonotesHomepage.iml (1)

1-12: Avoid committing IDE-specific files
Storing .idea module files in version control can lead to merge conflicts and leak user-specific settings. It’s best practice to exclude .idea/ and .iml files via the project’s root .gitignore.

Consider removing this file from the repo and adding to .gitignore:

.idea/
*.iml
README.md (1)

22-26: Clarify dev server invocation flags
Using npm run dev -- --open only works if your dev script forwards flags to SvelteKit. Confirm that your package.json includes:

"scripts": {
  "dev": "svelte-kit dev --open"
}

or adjust the README to match the actual script definition.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 40c666c and 5ecc3c3.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • static/favicon.png is excluded by !**/*.png
📒 Files selected for processing (20)
  • .gitignore (1 hunks)
  • .idea/.gitignore (1 hunks)
  • .idea/AxonotesHomepage.iml (1 hunks)
  • .idea/modules.xml (1 hunks)
  • .idea/vcs.xml (1 hunks)
  • .npmrc (1 hunks)
  • .prettierignore (1 hunks)
  • .prettierrc (1 hunks)
  • README.md (1 hunks)
  • eslint.config.js (1 hunks)
  • package.json (1 hunks)
  • src/app.css (1 hunks)
  • src/app.d.ts (1 hunks)
  • src/app.html (1 hunks)
  • src/lib/index.ts (1 hunks)
  • src/routes/+layout.svelte (1 hunks)
  • src/routes/+page.svelte (1 hunks)
  • svelte.config.js (1 hunks)
  • tsconfig.json (1 hunks)
  • vite.config.ts (1 hunks)
🔇 Additional comments (12)
src/lib/index.ts (1)

1-1: Placeholder file is appropriate
This guidance comment aligns with SvelteKit’s $lib convention. Once you start adding shared utilities, remember to export them here for clean imports.

.prettierignore (1)

1-6: Lock files excluded from formatting
Ignoring the various lock files ensures Prettier focuses on source code only. This list looks complete for npm, pnpm, yarn, and bun lock formats.

.npmrc (1)

1-1: Verify engine-strict enforcement
The engine-strict=true setting will only apply if you have declared an engines field in package.json. Please confirm that your package.json specifies the required Node.js version(s) so this restriction takes effect during installs.

.idea/modules.xml (1)

1-8: IntelliJ IDEA modules configuration is correct.
This file sets up the project modules for IntelliJ IDEA. Ensure your team agrees on committing the .idea folder contents; otherwise, consider moving these settings to a shared template or excluding them.

.idea/.gitignore (1)

1-8: IDE-specific ignore rules are in place.
This file correctly excludes workspace, shelf, HTTP Requests, and data source local files from version control. If you intend to commit .iml and modules.xml, ensure no conflicting entries exist in the root .gitignore.

vite.config.ts (1)

1-6:

✅ Verification successful

Verify Tailwind CSS plugin import
The import import tailwindcss from '@tailwindcss/vite'; is not part of the official Tailwind CSS/Vite integration. Double-check that @tailwindcss/vite exists in your dependencies and is intended. Typically Tailwind is configured via PostCSS (postcss.config.js) and tailwind.config.js, without a Vite plugin, or via a community plugin like vite-plugin-windicss.

To confirm installation, run:


🏁 Script executed:

#!/bin/bash
rg '"@tailwindcss/vite"' package.json

Length of output: 72


🌐 Web query:

npm package @tailwindcss/vite

💡 Result:

The @tailwindcss/vite package is a Vite plugin that integrates Tailwind CSS directly into your Vite project, streamlining the setup process and enhancing development efficiency. This plugin is particularly beneficial for projects using Tailwind CSS version 4 and later, as it simplifies the configuration by eliminating the need for a separate PostCSS setup.

Installation:

To incorporate @tailwindcss/vite into your project, execute the following command:

npm install tailwindcss @tailwindcss/vite

Configuration:

After installation, configure the plugin in your vite.config.js file:

import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [
    tailwindcss(),
    // ...other plugins
  ],
});

This setup ensures that Tailwind CSS is seamlessly integrated into your Vite build process.

Usage:

In your main CSS file (e.g., src/index.css), import Tailwind's base, components, and utilities:

@import 'tailwindcss';

This directive includes Tailwind's predefined styles into your project.

Additional Considerations:

  • Tailwind CSS Version: Ensure that your project is using Tailwind CSS version 4 or later to fully leverage the capabilities of @tailwindcss/vite.

  • Vite Configuration: If you encounter issues related to module resolution, such as errors indicating that @tailwindcss/vite is an ESM-only package, consider renaming your vite.config.js to vite.config.mjs to align with the module system. (stackoverflow.com)

By following these steps, you can effectively integrate Tailwind CSS into your Vite project, benefiting from a more streamlined and efficient development workflow.

Citations:


No action needed for Tailwind CSS plugin import
The @tailwindcss/vite package is a valid, officially supported Tailwind CSS v4+ plugin for Vite (confirmed in package.json and documentation). Your import and plugin configuration in vite.config.ts are correct.

src/app.d.ts (1)

1-14: Scaffolded declaration file looks good
Providing a global App namespace for future customization aligns with SvelteKit’s best practices. The placeholder interfaces and export {} ensure the file is treated as a module and ready for extension.

tsconfig.json (1)

1-19: TypeScript configuration looks good

The TypeScript configuration is well-structured with appropriate settings for a SvelteKit project. Setting strict: true is a good practice for catching type errors early, and the inclusion of source maps will help with debugging. The comments explaining path aliases and include/exclude handling provide valuable guidance for future maintenance.

svelte.config.js (1)

1-18: SvelteKit configuration is properly set up

The configuration uses the auto adapter which is ideal for an initial setup as it supports multiple deployment environments. The inclusion of vitePreprocess is correct for handling Svelte files with Vite. The comments provide good guidance on adapter selection for future reference.

src/app.html (1)

1-12: HTML template follows SvelteKit best practices

The template includes all necessary SvelteKit placeholders and optimizations like data-sveltekit-preload-data="hover" for improved performance. The integration with Skeleton UI via the data-theme="cerberus" attribute is properly implemented.

eslint.config.js (1)

1-36: ESLint configuration is comprehensive but has one consideration

The ESLint configuration correctly integrates JavaScript, TypeScript, Svelte, and Prettier rules using the modern flat config format. The setup for Svelte files with TypeScript support is properly configured.

Note: The 'no-undef' rule is turned off globally (line 23). While this is common in TypeScript projects since TypeScript's type checker handles this, be aware that this could potentially allow undeclared variables to pass linting. Consider if this aligns with your team's preferences.

package.json (1)

1-5: Metadata fields are well-defined
The project name, privacy flag, version, and module type are correctly specified for a private SvelteKit project.

.prettierrc Outdated
Comment on lines 9 to 10
"files": "*.svelte",
"options": {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure Svelte override covers nested files.
The pattern "*.svelte" only matches root‐level files. To target all Svelte components (e.g., in src/routes or src/lib), update to "**/*.svelte".

--- .prettierrc
+++ .prettierrc
@@ -9,4 +9,4 @@
-    {
-      "files": "*.svelte",
+    {
+      "files": "**/*.svelte",
       "options": {
         "parser": "svelte"
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"files": "*.svelte",
"options": {
{
"files": "**/*.svelte",
"options": {
"parser": "svelte"
}
}
🤖 Prompt for AI Agents
In the .prettierrc file at lines 9 to 10, the override pattern for Svelte files
uses "*.svelte", which only matches files in the root directory. Change this
pattern to "**/*.svelte" to ensure it matches all Svelte files recursively in
nested directories like src/routes or src/lib.

Comment on lines 3 to 7
let { children } = $props();
</script>

{@render children()}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use SvelteKit’s built-in slot API instead of $props() and {@render}
In SvelteKit layouts, the recommended pattern is to use <slot /> to render child routes. The current use of let { children } = $props() and {@render children()} is atypical and may not work as expected.

Proposed diff:

--- src/routes/+layout.svelte
3,7c3,4
-	let { children } = $props();
-</script>
-
-{@render children()}
+ </script>
+
+ <slot />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let { children } = $props();
</script>
{@render children()}
<script>
</script>
<slot />
🤖 Prompt for AI Agents
In src/routes/+layout.svelte around lines 3 to 7, replace the use of let {
children } = $props() and {@render children()} with the standard SvelteKit slot
API by removing those lines and adding a <slot /> element to render child routes
properly. This aligns with SvelteKit conventions and ensures correct rendering
of nested content.

package.json Outdated
Comment on lines 6 to 15
"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",
"format": "prettier --write .",
"lint": "prettier --check . && eslint ."
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use SvelteKit CLI instead of raw Vite commands
SvelteKit projects conventionally use the svelte-kit commands to ensure proper adapter integration, routing, and environment setup. Additionally, the prepare script should not silently swallow errors.

Apply this diff:

--- a/package.json
+++ b/package.json
@@ -7,10 +7,10 @@
-    "dev": "vite dev",
-    "build": "vite build",
-    "preview": "vite preview",
-    "prepare": "svelte-kit sync || echo ''",
+    "dev": "svelte-kit dev",
+    "build": "svelte-kit build",
+    "preview": "svelte-kit preview",
+    "prepare": "svelte-kit sync",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"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",
"format": "prettier --write .",
"lint": "prettier --check . && eslint ."
},
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"preview": "svelte-kit preview",
"prepare": "svelte-kit sync",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check . && eslint ."
},
🤖 Prompt for AI Agents
In package.json lines 6 to 15, replace the raw Vite commands in the "dev",
"build", and "preview" scripts with their corresponding "svelte-kit" CLI
commands to ensure proper SvelteKit integration. Also, update the "prepare"
script to run "svelte-kit sync" without swallowing errors by removing the "||
echo ''" part so any failures are visible.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
.gitignore (2)

91-99: Deduplicate build entries in SvelteKit section
You have both /build (line 19) and build/ (line 93) entries. Consider removing one to avoid redundancy and simplify maintenance.

Proposed diff:

-  build/  # For SvelteKit adapter-static or older Svelte projects

112-119: Clarify optional lockfile ignores
The commented-out lockfile ignore entries may confuse contributors. Clarify the intent or remove these lines if lockfiles should always be committed.

Example diff:

-# package-lock.json
-# yarn.lock
-# pnpm-lock.yaml
+# If you prefer to ignore lockfiles, uncomment the following:
+# package-lock.json
+# yarn.lock
+# pnpm-lock.yaml
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 5ecc3c3 and f820bcf.

📒 Files selected for processing (1)
  • .gitignore (1 hunks)
🔇 Additional comments (14)
.gitignore (14)

1-9: Comprehensive log exclusion section
This block effectively ignores various log files and directories (logs, *.log, npm-debug.log*, etc.), covering most common cases.


10-12: Diagnostic report patterns
Correctly ignores Node.js diagnostic reports (report.<version>.json).


13-20: Output directories exclusion
Appropriately excludes build/output directories for various deployment targets (.output, .vercel, .netlify, .wrangler, /.svelte-kit, /build).


21-26: Runtime data files
Nicely excludes PID and seed files (pids, *.pid, *.seed, *.pid.lock).


27-36: Coverage and instrumentation directories
Ignores instrumented libs (lib-cov), coverage outputs (coverage, *.lcov), and NYC test coverage (.nyc_output).


37-48: Task runner and binary addon artifacts
Excludes Grunt storage (.grunt), Bower dependencies (bower_components), node-waf files (.lock-wscript), and compiled addons (build/Release).


49-55: Dependency directories
Properly ignores node_modules/, jspm_packages/, and web_modules/.


56-64: TypeScript and ESLint caches
Covers TypeScript build info (*.tsbuildinfo) and ESLint cache (.eslintcache).


65-73: Microbundle and REPL histories
Ignores microbundle caches (.rpt2_cache/, .rts2_cache_*) and REPL history (.node_repl_history).


74-79: Archive and integrity files
Excludes npm pack tarballs (*.tgz) and Yarn integrity file (.yarn-integrity).


80-83: Vite timestamp files
Ignores Vite timestamped config backups (vite.config.js.timestamp-*, vite.config.ts.timestamp-*).


84-90: Environment variable files
Covers dotenv variants (.env, .env.*.local), ensuring secrets don’t leak.


100-111: IDE and editor artifacts
Appropriately ignores common IDE/editor files (.idea/, *.iml, macOS/Windows artifacts).


120-126: Secrets and local configs
Good exclusion of sensitive files (secrets.*, credentials.*, *.secret, local.settings.json).

@isvladu isvladu force-pushed the feat/initial-page branch from 1589238 to fc6546f Compare May 17, 2025 13:30
@ImGajeed76 ImGajeed76 requested a review from isvladu May 17, 2025 13:36
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
src/lib/components/Navbar.svelte (3)

7-13: Consider making navLinks reactive and adding types.

The navLinks array would benefit from a type definition and being marked as reactive for better maintainability.

-const navLinks = [
+interface NavLink {
+    href: string;
+    label: string;
+}
+
+const navLinks = $state<NavLink[]>([
    {href: '/', label: 'Home'},
    {href: '/about', label: 'About'},
    {href: '/features', label: 'Features'},
    {href: '/pricing', label: 'Pricing'},
    {href: '/community', label: 'Community'},
-];
+]);

39-41: Use a dynamic import path for the logo.

The current path uses a static reference to favicon.png which might not work in all environments. Consider using a more robust approach.

-    <img src="/favicon.png" alt="logo" class="max-h-10 mr-2">
+    <img src="{import.meta.env.BASE_URL}/favicon.png" alt="Axonotes logo" class="max-h-10 mr-2">
     Axonotes

68-72: Clean up empty props and improve modal transitions.

There are empty string properties in the Modal component that could be removed, and the transitions could be more descriptive.

    contentBase="bg-surface-100-900 p-4 space-y-4 shadow-xl w-[80%] max-w-[300px] h-screen"
    positionerJustify="justify-end"
-    positionerAlign=""
-    positionerPadding=""
-    transitionsPositionerIn={{ x: 400, duration: 200 }}
-    transitionsPositionerOut={{ x: 400, duration: 200 }}
+    transitionsPositionerIn={{ x: 400, duration: 200, easing: 'ease-out' }}
+    transitionsPositionerOut={{ x: 400, duration: 200, easing: 'ease-in' }}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between a4f320e and cf89ddd.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • axonotes-theme.css (1 hunks)
  • package.json (1 hunks)
  • src/app.css (1 hunks)
  • src/app.html (1 hunks)
  • src/lib/components/LightSwitch.svelte (1 hunks)
  • src/lib/components/Navbar.svelte (1 hunks)
  • src/routes/+layout.svelte (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • axonotes-theme.css
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/app.css
  • src/routes/+layout.svelte
  • src/app.html
  • package.json

Comment on lines 7 to 10
$effect(() => {
const mode = localStorage.getItem('mode') || 'light';
checked = mode === 'dark';
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for localStorage access.

The current implementation assumes localStorage is always available, but it can fail in private browsing mode or when cookies are disabled.

$effect(() => {
-    const mode = localStorage.getItem('mode') || 'light';
+    let mode = 'light';
+    try {
+        const storedMode = localStorage.getItem('mode');
+        if (storedMode) {
+            mode = storedMode;
+        }
+    } catch (error) {
+        console.warn('Unable to access localStorage:', error);
+    }
    checked = mode === 'dark';
});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$effect(() => {
const mode = localStorage.getItem('mode') || 'light';
checked = mode === 'dark';
});
$effect(() => {
let mode = 'light';
try {
const storedMode = localStorage.getItem('mode');
if (storedMode) {
mode = storedMode;
}
} catch (error) {
console.warn('Unable to access localStorage:', error);
}
checked = mode === 'dark';
});
🤖 Prompt for AI Agents
In src/lib/components/LightSwitch.svelte around lines 7 to 10, the code accesses
localStorage without error handling, which can cause failures in private
browsing or when cookies are disabled. Wrap the localStorage.getItem call in a
try-catch block to safely handle any exceptions. In the catch block, set a
default mode value to ensure the component continues to function without
crashing.

Comment on lines 28 to 36
{#if checked}
<button type="button" class="btn-icon preset-filled scheme-light" onclick={() => onCheckedChange({checked: false})}>
<Sun/>
</button>
{:else}
<button type="button" class="btn-icon preset-filled scheme-dark" onclick={() => onCheckedChange({checked: true})}>
<Moon/>
</button>
{/if}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve accessibility and use Svelte's event handling.

The buttons lack proper accessibility attributes, and it's better to use Svelte's on:click directive instead of onclick.

<div class="relative">
    {#if checked}
-        <button type="button" class="btn-icon preset-filled scheme-light" onclick={() => onCheckedChange({checked: false})}>
+        <button 
+            type="button" 
+            class="btn-icon preset-filled scheme-light" 
+            on:click={() => onCheckedChange({checked: false})}
+            aria-label="Switch to light mode"
+        >
            <Sun/>
        </button>
    {:else}
-        <button type="button" class="btn-icon preset-filled scheme-dark" onclick={() => onCheckedChange({checked: true})}>
+        <button 
+            type="button" 
+            class="btn-icon preset-filled scheme-dark" 
+            on:click={() => onCheckedChange({checked: true})}
+            aria-label="Switch to dark mode"
+        >
            <Moon/>
        </button>
    {/if}
</div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{#if checked}
<button type="button" class="btn-icon preset-filled scheme-light" onclick={() => onCheckedChange({checked: false})}>
<Sun/>
</button>
{:else}
<button type="button" class="btn-icon preset-filled scheme-dark" onclick={() => onCheckedChange({checked: true})}>
<Moon/>
</button>
{/if}
<div class="relative">
{#if checked}
<button
type="button"
class="btn-icon preset-filled scheme-light"
on:click={() => onCheckedChange({checked: false})}
aria-label="Switch to light mode"
>
<Sun/>
</button>
{:else}
<button
type="button"
class="btn-icon preset-filled scheme-dark"
on:click={() => onCheckedChange({checked: true})}
aria-label="Switch to dark mode"
>
<Moon/>
</button>
{/if}
</div>
🤖 Prompt for AI Agents
In src/lib/components/LightSwitch.svelte around lines 28 to 36, the buttons lack
accessibility attributes like aria-pressed to indicate their state, and the
event handlers use the native onclick attribute instead of Svelte's on:click
directive. To fix this, add appropriate accessibility attributes such as
aria-pressed reflecting the checked state to each button, and replace onclick
with on:click for event handling following Svelte conventions.

Comment on lines 80 to 82
<button class="btn" onclick={closeMobileMenu}>
<X/>
</button>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use Svelte's event handling and add accessibility attributes.

Replace the onclick attribute with Svelte's on:click directive and add aria attributes for better accessibility.

-<button class="btn" onclick={closeMobileMenu}>
+<button 
+    class="btn" 
+    on:click={closeMobileMenu}
+    aria-label="Close mobile menu"
+>
    <X/>
</button>
🤖 Prompt for AI Agents
In src/lib/components/Navbar.svelte around lines 80 to 82, replace the HTML
onclick attribute with Svelte's on:click directive for event handling.
Additionally, add appropriate aria attributes such as aria-label to the button
element to improve accessibility, ensuring screen readers can identify the
button's purpose.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/routes/+error.svelte (1)

60-66: Nice touch with the home link – consider prefetching

Minor UX win: add sveltekit:prefetch to the anchor so the home page is warmed in the background.

-<a href="/" class="btn …">
+<a href="/" sveltekit:prefetch class="btn …">
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7426b19 and b2b31e6.

⛔ Files ignored due to path filters (1)
  • static/page-not-found.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • src/routes/+error.svelte (1 hunks)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/routes/sitemap.xml/+server.ts (2)

24-30: Fine-tune priority and change-freq
A blanket priority 0.7/1.0 and fixed weekly change frequency may mislead crawlers. At minimum, expose helpers so each route can opt-in to custom values (e.g., features page vs. legal pages).

Not blocking, but worth revisiting.


43-47: Include public in Cache-Control header
Without the public directive, some intermediary caches might ignore the header.

-"Cache-Control": `max-age=0, s-maxage=${60 * 60 * 24}`,
+"Cache-Control": `public, max-age=0, s-maxage=${60 * 60 * 24}`,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2b31e6 and 1c933a6.

📒 Files selected for processing (4)
  • src/app.d.ts (1 hunks)
  • src/routes/+error.svelte (1 hunks)
  • src/routes/sitemap.xml/+server.ts (1 hunks)
  • static/robots.txt (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • static/robots.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/routes/+error.svelte
  • src/app.d.ts
🔇 Additional comments (2)
src/routes/sitemap.xml/+server.ts (2)

13-21: Path normalisation is brittle
The triple replace() chain silently fails if any import path deviates (e.g. nested index/+page.svelte, back-slashes on Windows, or a possible future +page.ts). Using new URL or path.posix utilities is safer.

-import "/src/routes", ""
-.replace("/+page.svelte", "")
-.replace(/\/$/, "")
+const route = p
+  .replace(/^.*\/src\/routes/, "")
+  .replace(/\/\+page\.svelte$/, "")
+  .replace(/\/index$/, "")

1-1: Import path is correct – good job
Using the generated route types keeps the handler strongly typed.

Comment on lines 7 to 11
// Use Vite's glob import to find all +page.svelte files
// The type for import.meta.glob is generally { [key: string]: () => Promise<unknown> }
const pages: Record<string, () => Promise<unknown>> = import.meta.glob(
"/src/routes/**/+page.svelte"
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid per-request import.meta.glob – hoist it and exclude dynamic routes
import.meta.glob() is resolved at build time, but the expression is still executed every time the endpoint is hit, incurring unnecessary work.
Two additional issues:

  1. It also matches dynamic segments like [slug], resulting in bogus <loc> entries (/blog/[slug]).
  2. Windows builds will emit back-slashes, breaking the replacement logic.

Consider hoisting and filtering once at module scope:

-export const GET: RequestHandler = async ({ setHeaders, url }) => {
-    const pages: Record<string, () => Promise<unknown>> =
-        import.meta.glob("/src/routes/**/+page.svelte");
+const allPages = Object.keys(
+  import.meta.glob("/src/routes/**/+page.svelte", { eager: false })
+)
+  // strip dynamic parameters
+  .filter((p) => !/\[[^\]]+\]/.test(p));
+
+export const GET: RequestHandler = async ({ setHeaders, url }) => {

This removes the per-request overhead and keeps dynamic placeholders out of the sitemap.

🤖 Prompt for AI Agents
In src/routes/sitemap.xml/+server.ts around lines 7 to 11, the import.meta.glob
call is inside the request handler, causing it to run on every request and
include dynamic routes with placeholders like [slug], which should be excluded.
Move the import.meta.glob call to the module scope (outside the handler) to run
it once at build time, then filter out any paths containing dynamic segments
such as brackets. Also, normalize paths to use forward slashes to avoid issues
on Windows. This will prevent unnecessary work per request and exclude invalid
sitemap entries.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
README.md (2)

98-100: Suggest adding polite phrasing to Contributing bullets
For consistency with the “Please open an issue” tone, consider adding “Please” to the Design Ideas bullet.

Proposed diff:

- - 🎨 **Design Ideas?** Open an issue to discuss your suggestions. We're keen to make the site as user-friendly and appealing as possible.
+ - 🎨 **Design Ideas?** Please open an issue to discuss your suggestions. We're keen to make the site as user-friendly and appealing as possible.

105-105: Suggest polite wording for commit instruction
Consider changing “Make sure” to “Please make sure” for a more courteous tone.

Proposed diff:

- 4.  Commit your changes (`git commit -m 'Add some amazing feature'`). **_Make sure to sign your commits with gpg!_**
+ 4.  Commit your changes (`git commit -m 'Add some amazing feature'`). **_Please make sure to sign your commits with gpg!_**
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c933a6 and 915276a.

📒 Files selected for processing (1)
  • README.md (3 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[style] ~100-~100: Consider using polite language here.
Context: ... help users understand Axonotes better, let us know via an issue. - 🛠️ **Code Contribution...

(INSERT_PLEASE)

🔇 Additional comments (5)
README.md (5)

38-45: Approve core feature list formatting
The new list entries under “We’re building an all-in-one academic suite focused on:” are clear, concise, and consistently formatted.


55-58: Approve purpose bullet list formatting
The repository purpose bullets are well-structured and use consistent markdown list syntax.


62-62: Approve star history badge simplification
Replacing the complex <picture> block with a single markdown badge link improves readability and maintainability.


68-69: Approve tech stack list formatting
The Tech Stack section is clearly presented with consistent bullet markers and emphasis.


112-113: Approve feedback channels formatting
The “Share Your Thoughts” and “Quick Survey” bullets are well-formatted and clear.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
README.md (5)

54-58: Verify Consistent List Formatting in “About This Website” Section
This block also uses dashes for list items. Ensure all list sections follow the same bullet convention for a cohesive look.


68-70: Consistent Tech Stack Bullets
These entries are clear. Optionally, you could add target="_blank" to external links for better UX in documentation.


98-100: Add Politeness to Community Call-to-Action
Consider adding “please” to soften the tone (e.g., “Please let us know via an issue.”) for a more inviting style.


105-105: Commit Signing Reminder Styling
The italic GPG reminder is effective. You might also consider using a callout block (e.g., a > **Note:**) for consistency with other admonitions.


120-125: Review Social Links Section
All social URLs are listed clearly. Confirm that each link points to the official account and consider adding icons for quicker recognition.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 915276a and 4ec9ce3.

📒 Files selected for processing (3)
  • README.md (3 hunks)
  • src/routes/about/+page.svelte (1 hunks)
  • src/routes/pricing/+page.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/routes/pricing/+page.svelte
  • src/routes/about/+page.svelte
🧰 Additional context used
🪛 LanguageTool
README.md

[style] ~100-~100: Consider using polite language here.
Context: ... help users understand Axonotes better, let us know via an issue. - 🛠️ **Code Contribution...

(INSERT_PLEASE)

🔇 Additional comments (3)
README.md (3)

38-45: Inconsistent Summary vs Actual Bullet Style
The AI summary mentioned switching to plus-sign bullets, but this section still uses dashes (-). Please align the list style across the README or update the summary to reflect the chosen format.

Likely an incorrect or invalid review comment.


62-62: Approve Simplified Star History Badge
Switching to a single markdown badge is concise and clear—great simplification.


109-110: Validate Contact Methods
The email and survey URLs look correct. Please verify that these endpoints are active and monitored before release.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (7)
src/lib/components/Navbar.svelte (1)

116-116: Replace onclick with Svelte's on:click directive.

The component still uses HTML onclick attributes instead of Svelte's event handling, which was flagged in previous reviews.

-                                    onclick={closeMobileMenu}
+                                    on:click={closeMobileMenu}

Apply this change to all three instances: lines 116, 131, and 157.

Also applies to: 131-131, 157-157

src/routes/community/+page.svelte (1)

90-92: Fix the Svelte event handler syntax.

The onclick attribute is not valid in Svelte. Use the on:click directive instead.

Apply this diff to fix the event handler:

-<button onclick={() => (heartClicked = true)} class={heartClicked ? "cursor-default" : ""}>
+<button on:click={() => (heartClicked = true)} class={heartClicked ? "cursor-default" : ""}>
src/routes/+page.svelte (3)

468-476: Add descriptive aria-label for final CTA.

The final Discord link should include an aria-label for improved screen reader support.

Apply this diff:

<a
    href="https://discord.gg/myBMaaDeQu"
    target="_blank"
    rel="noopener noreferrer"
    class="btn preset-filled-secondary-500 inline-flex min-h-[44px] items-center justify-center gap-2 px-4 text-sm text-white sm:px-6 sm:text-base"
+   aria-label="Join Axonotes waitlist on Discord"
>
    {m.home_finalCta_button()}
    <ExternalLink class="h-3 w-3 sm:h-4 sm:w-4" />
</a>

95-107: Enhance accessibility for primary CTA button.

The Discord link button lacks proper accessibility attributes and could benefit from better semantic markup.

Apply this diff to improve accessibility:

<a
    href="https://discord.gg/myBMaaDeQu"
    target="_blank"
    rel="noopener noreferrer"
    class="btn preset-filled-primary-500 inline-flex min-h-[44px] items-center justify-center gap-2 px-4 text-sm text-white sm:px-6 sm:text-base"
+   aria-label="Join Axonotes Discord community waitlist"
>
    <MessageCircle class="h-4 w-4 sm:h-5 sm:w-5" />
    <span class="xs:inline hidden"
        >{m.home_hero_cta_primary()}</span
    >
    {m.home_hero_cta_primary_mobile()}
    <ArrowRight class="h-3 w-3 sm:h-4 sm:w-4" />
</a>

228-249: Improve accessibility for core value cards.

The value cards need better keyboard navigation and semantic structure for screen readers.

Apply this pattern to enhance accessibility:

{#each coreValues as value (value.title)}
    {@const Icon = value.icon}
-    <div class="card p-4 text-center sm:p-6">
+    <div 
+        class="card p-4 text-center sm:p-6" 
+        role="article" 
+        aria-labelledby="value-{value.title.toLowerCase().replace(/\s+/g, '-')}"
+        tabindex="0"
+    >
        <div
            class="bg-primary-100 dark:bg-primary-900/30 mx-auto mb-3 flex h-10 w-10 items-center justify-center rounded-lg sm:mb-4 sm:h-12 sm:w-12"
        >
            <Icon
                class="text-primary-600 dark:text-primary-400 h-5 w-5 sm:h-6 sm:w-6"
+               aria-hidden="true"
            />
        </div>
        <h3
+           id="value-{value.title.toLowerCase().replace(/\s+/g, '-')}"
            class="text-surface-900 dark:text-surface-100 mb-2 text-sm font-semibold sm:text-base"
        >
            {value.title}
        </h3>
src/routes/about/+page.svelte (2)

437-440: Fix Svelte event handler syntax for heart button.

The onclick attribute is not valid in Svelte. Use the on:click directive instead.

Apply this diff to fix the event handler:

<button
-   onclick={() => (heartClicked = true)}
+   on:click={() => (heartClicked = true)}
    class={heartClicked ? "cursor-default" : ""}
>

474-482: Remove target="_blank" for internal navigation.

The community link points to an internal page but uses target="_blank", which will unnecessarily open a new tab and confuse users.

Apply this diff to fix the internal navigation:

<a
    href="/community"
-   target="_blank"
-   rel="noopener noreferrer"
    class="btn preset-filled-primary-500 inline-flex items-center justify-center gap-2 px-4 py-2 text-sm text-white md:px-6 md:py-3 md:text-base"
>
    <Users class="h-4 w-4" />
    {m.about_cta_button1()}
</a>
🧹 Nitpick comments (3)
src/app.html (2)

2-6: Hard-coded data-theme limits runtime theme switching

You later toggle colour themes client-side, but this static attribute locks the root to "axonotes-theme".
Consider reading the user-preferred theme from localStorage (or prefers-color-scheme) in a tiny inline script and updating the attribute before first paint to prevent FOUC.


7-12: Add basic SEO / PWA meta tags while the template is fresh

Beyond title & viewport, include:

+        <meta name="description" content="Axonotes – your neuroscience note-taking companion" />
+        <link rel="manifest" href="%sveltekit.assets%/site.webmanifest" />
+        <meta name="theme-color" content="#101010" media="(prefers-color-scheme: dark)" />

Those small additions improve search discoverability and PWA install experience.

src/lib/components/LanguageSwitcher.svelte (1)

23-67: Consider enhancing keyboard navigation and focus management.

The popover implementation is solid but could benefit from improved keyboard navigation within the language list and proper focus management when opening/closing.

Consider adding:

  • Arrow key navigation between language options
  • Focus management to return focus to trigger after selection
  • Enhanced ARIA labels for better screen reader support
+    import { tick } from 'svelte';
+    
+    let popoverContent: HTMLElement;
+    
+    async function handleLanguageSelect(event: Event) {
+        closePopover();
+        await tick();
+        // Return focus to trigger button
+        (event.target as HTMLElement)?.closest('[data-trigger]')?.focus();
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a4754f and cabdccd.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • .github/workflows/ninja_i18n.yml (1 hunks)
  • messages/de.json (1 hunks)
  • messages/en.json (1 hunks)
  • package.json (1 hunks)
  • project.inlang/.gitignore (1 hunks)
  • project.inlang/project_id (1 hunks)
  • project.inlang/settings.json (1 hunks)
  • src/app.d.ts (1 hunks)
  • src/app.html (1 hunks)
  • src/hooks.server.ts (1 hunks)
  • src/hooks.ts (1 hunks)
  • src/lib/components/LanguageSwitcher.svelte (1 hunks)
  • src/lib/components/Navbar.svelte (1 hunks)
  • src/lib/components/SelfHostingSection.svelte (1 hunks)
  • src/lib/i18n.ts (1 hunks)
  • src/routes/+error.svelte (1 hunks)
  • src/routes/+layout.svelte (1 hunks)
  • src/routes/+page.svelte (1 hunks)
  • src/routes/about/+page.svelte (1 hunks)
  • src/routes/community/+page.svelte (1 hunks)
  • src/routes/features/+page.server.ts (1 hunks)
  • src/routes/features/+page.svelte (1 hunks)
  • src/routes/pricing/+page.svelte (1 hunks)
  • vite.config.ts (1 hunks)
✅ Files skipped from review due to trivial changes (9)
  • project.inlang/.gitignore
  • src/hooks.ts
  • project.inlang/project_id
  • src/lib/i18n.ts
  • project.inlang/settings.json
  • .github/workflows/ninja_i18n.yml
  • messages/de.json
  • messages/en.json
  • src/lib/components/SelfHostingSection.svelte
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/routes/+error.svelte
  • src/routes/pricing/+page.svelte
  • src/routes/features/+page.svelte
  • src/routes/+layout.svelte
  • src/routes/features/+page.server.ts
  • package.json
🧰 Additional context used
🧠 Learnings (5)
src/app.d.ts (3)
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In SvelteKit 2.12+ with Svelte 5, the page object is imported from `$app/state` (not the deprecated `$app/stores`) and accessed directly without the `$` prefix. So use `import { page } from "$app/state"` and then `page.status`, `page.error`, `page.url.pathname` etc. directly. The old `$app/stores` with `$page.status` syntax is deprecated. The migration guide specifically says to remove the `$` prefix when accessing variables in templates.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:1-5
Timestamp: 2025-06-17T20:47:26.756Z
Learning: In Svelte 5 with SvelteKit 2.12+, use `import { page } from "$app/state"` instead of `import { page } from "$app/stores"`. The page object from $app/state is a reactive state object that doesn't require the `$` prefix for dereferencing (e.g., `page.status`, `page.data`, `page.error?.message`). The `$app/stores` module is deprecated in newer SvelteKit versions.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In Svelte 5, the `page` object is imported from `$app/state` (not `$app/stores` like in Svelte 4) and can be accessed directly as `page.status`, `page.error`, etc. without the `$` prefix. The reactive `$` syntax is not needed when using Svelte 5's state system.
src/routes/community/+page.svelte (4)
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In Svelte 5, the `page` object is imported from `$app/state` (not `$app/stores` like in Svelte 4) and can be accessed directly as `page.status`, `page.error`, etc. without the `$` prefix. The reactive `$` syntax is not needed when using Svelte 5's state system.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:1-5
Timestamp: 2025-06-17T20:47:26.756Z
Learning: In Svelte 5 with SvelteKit 2.12+, use `import { page } from "$app/state"` instead of `import { page } from "$app/stores"`. The page object from $app/state is a reactive state object that doesn't require the `$` prefix for dereferencing (e.g., `page.status`, `page.data`, `page.error?.message`). The `$app/stores` module is deprecated in newer SvelteKit versions.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In SvelteKit 2.12+ with Svelte 5, the page object is imported from `$app/state` (not the deprecated `$app/stores`) and accessed directly without the `$` prefix. So use `import { page } from "$app/state"` and then `page.status`, `page.error`, `page.url.pathname` etc. directly. The old `$app/stores` with `$page.status` syntax is deprecated. The migration guide specifically says to remove the `$` prefix when accessing variables in templates.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In Svelte 5 with the new runes system, the `page` object should be imported from `$app/state` and accessed directly as `page.status`, `page.error`, etc. without the `$` prefix. This is different from earlier versions where you'd import from `$app/stores` and use `$page.status`. The direct access pattern without `$` is correct for Svelte 5's state system.
src/routes/+page.svelte (4)
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In Svelte 5, the `page` object is imported from `$app/state` (not `$app/stores` like in Svelte 4) and can be accessed directly as `page.status`, `page.error`, etc. without the `$` prefix. The reactive `$` syntax is not needed when using Svelte 5's state system.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In SvelteKit 2.12+ with Svelte 5, the page object is imported from `$app/state` (not the deprecated `$app/stores`) and accessed directly without the `$` prefix. So use `import { page } from "$app/state"` and then `page.status`, `page.error`, `page.url.pathname` etc. directly. The old `$app/stores` with `$page.status` syntax is deprecated. The migration guide specifically says to remove the `$` prefix when accessing variables in templates.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In Svelte 5 with the new runes system, the `page` object should be imported from `$app/state` and accessed directly as `page.status`, `page.error`, etc. without the `$` prefix. This is different from earlier versions where you'd import from `$app/stores` and use `$page.status`. The direct access pattern without `$` is correct for Svelte 5's state system.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:1-5
Timestamp: 2025-06-17T20:47:26.756Z
Learning: In Svelte 5 with SvelteKit 2.12+, use `import { page } from "$app/state"` instead of `import { page } from "$app/stores"`. The page object from $app/state is a reactive state object that doesn't require the `$` prefix for dereferencing (e.g., `page.status`, `page.data`, `page.error?.message`). The `$app/stores` module is deprecated in newer SvelteKit versions.
src/routes/about/+page.svelte (4)
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In Svelte 5, the `page` object is imported from `$app/state` (not `$app/stores` like in Svelte 4) and can be accessed directly as `page.status`, `page.error`, etc. without the `$` prefix. The reactive `$` syntax is not needed when using Svelte 5's state system.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:1-5
Timestamp: 2025-06-17T20:47:26.756Z
Learning: In Svelte 5 with SvelteKit 2.12+, use `import { page } from "$app/state"` instead of `import { page } from "$app/stores"`. The page object from $app/state is a reactive state object that doesn't require the `$` prefix for dereferencing (e.g., `page.status`, `page.data`, `page.error?.message`). The `$app/stores` module is deprecated in newer SvelteKit versions.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In SvelteKit 2.12+ with Svelte 5, the page object is imported from `$app/state` (not the deprecated `$app/stores`) and accessed directly without the `$` prefix. So use `import { page } from "$app/state"` and then `page.status`, `page.error`, `page.url.pathname` etc. directly. The old `$app/stores` with `$page.status` syntax is deprecated. The migration guide specifically says to remove the `$` prefix when accessing variables in templates.
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In Svelte 5 with the new runes system, the `page` object should be imported from `$app/state` and accessed directly as `page.status`, `page.error`, etc. without the `$` prefix. This is different from earlier versions where you'd import from `$app/stores` and use `$page.status`. The direct access pattern without `$` is correct for Svelte 5's state system.
src/app.html (1)
Learnt from: ImGajeed76
PR: axonotes/AxonotesHomepage#1
File: src/routes/+error.svelte:7-18
Timestamp: 2025-06-17T20:48:00.743Z
Learning: In SvelteKit 2.12+ with Svelte 5, the page object is imported from `$app/state` (not the deprecated `$app/stores`) and accessed directly without the `$` prefix. So use `import { page } from "$app/state"` and then `page.status`, `page.error`, `page.url.pathname` etc. directly. The old `$app/stores` with `$page.status` syntax is deprecated. The migration guide specifically says to remove the `$` prefix when accessing variables in templates.
🧬 Code Graph Analysis (1)
src/hooks.server.ts (1)
src/lib/i18n.ts (1)
  • i18n (5-5)
🪛 Biome (1.9.4)
src/app.d.ts

[error] 22-23: This empty export is useless because there's another export or import.

This import makes useless the empty export.

Safe fix: Remove this useless empty export.

(lint/complexity/noUselessEmptyExport)

🪛 HTMLHint (1.5.0)
src/app.html

[error] 12-12: <title> must be present in tag.

(title-require)

🔇 Additional comments (8)
src/lib/components/LanguageSwitcher.svelte (1)

46-46: Verify i18n.route API before merging

I wasn’t able to locate the i18n.route definition in the repo—please confirm that it accepts both a pathname and a target-language argument (e.g. route(pathname, lang)) before you apply the suggested diff:

- href={i18n.route(page.url.pathname)}
+ href={i18n.route(page.url.pathname, lang)}

Ensure that any consumer of i18n.route is updated accordingly and that existing routes continue to resolve correctly.

src/lib/components/Navbar.svelte (1)

1-26: LGTM - Clean component structure.

The script setup is well-organized with proper imports, localized navigation links, and clean state management using Svelte 5 patterns.

src/hooks.server.ts (1)

1-6: LGTM - Proper i18n server hook setup.

The server hook correctly integrates the Paraglide i18n handler using SvelteKit's sequence utility. This follows the standard pattern for internationalization setup.

vite.config.ts (2)

12-14: Consider security implications of allowedHosts configuration.

The preview configuration allows all subdomains of .axonotes.ch. Ensure this aligns with your deployment and security requirements.

Verify that this host configuration is intended for your deployment setup and doesn't expose the development server unnecessarily.


1-15: LGTM - Well-configured Vite setup.

The plugin configuration correctly integrates Paraglide for i18n, Tailwind CSS for styling, and SvelteKit. The plugin order is appropriate and the Paraglide configuration matches the project structure.

src/app.d.ts (3)

23-23: Empty export is necessary for module declaration.

The static analysis tool flagged this as useless, but the empty export statement is actually required in TypeScript to treat this file as a module when it only contains declare statements.

The Biome linter is incorrect in this case - removing the empty export would cause TypeScript compilation issues.


1-21: LGTM - Proper TypeScript declarations for i18n integration.

The type declarations correctly extend the App.Locals interface with Paraglide types and provide proper typing for the internationalization setup. The import paths and type usage align with the project's i18n infrastructure.


17-21: Good module declaration for .svx files.

The module declaration properly types .svx files as Svelte components, which supports the markdown-based content components used in the project.

Comment on lines +320 to +330
<button
onclick={() => (coffeeClicked = true)}
class={coffeeClicked ? "cursor-default" : ""}
>
<Coffee
class="text-primary-500 h-5 w-5 {coffeeClicked
? 'animate-bounce'
: 'hover:scale-110'} transition-all duration-200 md:h-6 md:w-6"
aria-hidden="true"
/>
</button>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance accessibility for interactive coffee button.

The coffee button needs proper accessibility attributes for screen readers and keyboard users.

Apply this diff to improve accessibility:

<button
    on:click={() => (coffeeClicked = true)}
    class={coffeeClicked ? "cursor-default" : ""}
+   aria-label={coffeeClicked ? "Development status animation activated" : "Click to animate development status"}
+   aria-pressed={coffeeClicked}
+   disabled={coffeeClicked}
>
    <Coffee
        class="text-primary-500 h-5 w-5 {coffeeClicked
            ? 'animate-bounce'
            : 'hover:scale-110'} transition-all duration-200 md:h-6 md:w-6"
        aria-hidden="true"
    />
</button>

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/routes/about/+page.svelte around lines 320 to 330, the coffee button
lacks accessibility attributes. Add an aria-label describing the button's
purpose, ensure the button is focusable and operable via keyboard by using
standard button element behavior, and consider adding role or aria-pressed
attributes if the button toggles state. This will improve screen reader and
keyboard user experience.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/app.html (1)

7-11: Add a mandatory <title> element for spec-compliance and SEO

The <head> block still omits a <title> tag, which is required by the HTML specification and flagged by HTMLHint. Search-engine crawlers and accessibility tools rely on it.

         <meta charset="utf-8" />
         <meta name="viewport" content="width=device-width, initial-scale=1" />
+
+        <!-- Document title (static fallback; dynamic titles are appended via %sveltekit.head%) -->
+        <title>Axonotes</title>
🧹 Nitpick comments (1)
src/app.html (1)

32-43: Consider distinct theme-color values for light vs dark schemes

Both prefers-color-scheme meta tags use #6089f7. If the dark theme background is substantially darker, that hue may clash with browser UI elements (e.g., Android address bar). Providing a darker variant (or omitting the dark entry to let the user-agent derive it) yields a more polished appearance.

-        <meta
-            name="theme-color"
-            content="#6089f7"
-            media="(prefers-color-scheme: dark)"
-        />
+        <meta
+            name="theme-color"
+            content="#2743af" <!-- example darker shade -->
+            media="(prefers-color-scheme: dark)"
+        />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cabdccd and 066b3ca.

⛔ Files ignored due to path filters (6)
  • static/apple-touch-icon.png is excluded by !**/*.png
  • static/favicon-96x96.png is excluded by !**/*.png
  • static/favicon.ico is excluded by !**/*.ico
  • static/favicon.svg is excluded by !**/*.svg
  • static/web-app-manifest-192x192.png is excluded by !**/*.png
  • static/web-app-manifest-512x512.png is excluded by !**/*.png
📒 Files selected for processing (5)
  • src/app.html (1 hunks)
  • src/lib/components/Navbar.svelte (1 hunks)
  • src/lib/components/SelfHostingSection.svelte (1 hunks)
  • src/routes/+layout.svelte (1 hunks)
  • static/site.webmanifest (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • static/site.webmanifest
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/lib/components/Navbar.svelte
  • src/lib/components/SelfHostingSection.svelte
  • src/routes/+layout.svelte
🧰 Additional context used
🪛 HTMLHint (1.5.0)
src/app.html

[error] 58-58: <title> must be present in tag.

(title-require)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/app.html (1)

55-58: Add a <title> fallback before %sveltekit.head%

The document still lacks a <title> element, which violates the HTML spec and hampers SEO. The previous review already highlighted this; please address it or explicitly justify why dynamic titles alone are sufficient. A minimal, localised fallback keeps validators quiet and covers error pages where no dynamic head is rendered.

         <meta name="referrer" content="strict-origin-when-cross-origin" />

+        <!-- Fallback title (overridden by %sveltekit.head% when present) -->
+        <title>Axonotes</title>
+
         %sveltekit.head%
🧹 Nitpick comments (1)
src/app.html (1)

30-45: Consider adding a meta description for basic SEO

A short, meaningful meta name="description" improves search-engine snippets and link previews.

         <link rel="manifest" href="%sveltekit.assets%/site.webmanifest" />

+        <!-- SEO -->
+        <meta
+            name="description"
+            content="Axonotes – the next-generation note-taking companion for neuroscience students and professionals."
+        />
+
         <!-- Theme and colors -->
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 066b3ca and 73438fc.

📒 Files selected for processing (1)
  • src/app.html (1 hunks)
🧰 Additional context used
🪛 HTMLHint (1.5.0)
src/app.html

[error] 58-58: <title> must be present in tag.

(title-require)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants