-
Notifications
You must be signed in to change notification settings - Fork 0
Create app #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Create app #1
Conversation
|
Warning Rate limit exceeded@adityaoberai has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 43 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
WalkthroughAdds a SvelteKit application scaffold (routes, layout, static assets, UI page) and Appwrite client wiring. Introduces a central rules generator (src/lib/rules-generator.js), a large set of language/framework template modules under src/lib/languages, SDK version utilities with caching and fallback (src/lib/utils/versions.js), server API endpoints (src/routes/api/*), helper scripts, and many tooling/config files (package.json, pnpm-workspace.yaml, eslint.config.js, Prettier, TypeScript, Vite, svelte.config.js, .npmrc, ignore files). The LICENSE file content was removed. Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Areas to focus during review:
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
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. Comment |
Cursor Rules GeneratorProject ID: Tip SSR frameworks are fully supported with configurable build runtimes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (21)
README.md (1)
1-38: Replace generic README with project-specific documentation.The current README is SvelteKit scaffolding boilerplate and lacks any context about the Appwrite Cursor Rules Generator. Users need to understand the project's purpose, core features, and how to use the rules generator.
Consider adding sections covering:
- Project description and purpose
- Quick-start guide for the rules generator
- Appwrite integration details
- Configuration and environment setup
- Example workflows
- Build and deployment instructions
- Links to relevant Appwrite documentation
src/lib/appwrite.js (2)
2-2: Consider removing@ts-ignorein favor of proper TypeScript configuration.SvelteKit's
$env/static/publicshould be recognized by TypeScript iftsconfig.jsonextends.svelte-kit/tsconfig.json. The@ts-ignoremay hide legitimate type errors.
5-10: EmptyprojectIdfallback could cause confusing runtime errors.If
PUBLIC_APPWRITE_PROJECT_IDis not set, the client initializes with an empty string. Appwrite will fail at runtime with an unclear error. Consider validating or throwing early:const endpoint = PUBLIC_APPWRITE_ENDPOINT || 'https://cloud.appwrite.io/v1'; -const projectId = PUBLIC_APPWRITE_PROJECT_ID || ''; +const projectId = PUBLIC_APPWRITE_PROJECT_ID; + +if (!projectId) { + throw new Error('PUBLIC_APPWRITE_PROJECT_ID environment variable is required'); +}src/lib/languages/python/flask.js (1)
3-7: Consider expanding Flask security guidance.The current security notes are minimal (2 bullet points) compared to server-side templates which provide more comprehensive guidance (3-4 bullet points with specifics about API keys and admin access).
Consider adding Flask-specific security best practices such as:
- Secret key management (Flask's SECRET_KEY configuration)
- Disabling debug mode in production
- CORS configuration if building APIs
- Session security settings
src/lib/languages/js/vue.js (1)
5-8: Consider using.env.localinstead of.envfor Vue.Vue.js projects (using Vite) conventionally use
.env.localfor local environment variables that should not be committed to version control. The.envfile is typically committed and contains non-sensitive defaults.Note that the
clientSecurityWithEnvhelper defaults to.env.local, suggesting this is the preferred pattern for client-side frameworks.Apply this diff to align with Vue.js conventions:
export const vue = createFrameworkTemplate({ installation: jsInstall, - securityNotes: clientSecurityWithEnv('.env') + securityNotes: clientSecurityWithEnv('.env.local') });src/lib/languages/dotnet/vanilla.js (1)
4-7: Consider adding security notes for consistency.The .NET template uses empty
securityNotes, while other server-side SDK templates (e.g., Next.js at line 7 in nextjs.js, Kotlin at line 45 in kotlin/index.js) includeserverSecuritynotes about API key protection and environment variables. Consider adding appropriate security guidance for .NET developers.Apply this diff to add security notes:
-export const vanilla = createFrameworkTemplate({ - installation: dotnetInstall, - securityNotes: '' -}); +import { serverSecurity } from '../common/security.js'; + +export const vanilla = createFrameworkTemplate({ + installation: dotnetInstall, + securityNotes: serverSecurity +});src/lib/languages/react-native/vanilla.js (1)
4-10: Consider extracting security notes to a shared constant.The inline
securityNotesstring duplicates content that exists insrc/lib/languages/common/security.js(e.g.,clientSecurity). For consistency with other modules likejs/vanilla.jsthat reference shared security constants, consider importing and reusing from the common security module.This is a minor consistency suggestion and the current implementation works correctly.
src/lib/languages/swift/index.js (1)
31-35: Consider adding security notes for the Swift client SDK.The
securityNotesparameter is an empty string, which will result in no security guidance in the generated template. Other client SDK templates (e.g.,react-native/vanilla.js,js/vanilla.js) include best practices about environment variables, API key handling, and singleton initialization.For consistency and user guidance, consider adding appropriate client-side security notes:
export const vanilla = async () => { const version = await getSDKVersion('client-apple'); const installation = generateInstallationTemplate(version); - return createFrameworkTemplate({ installation, securityNotes: '' }); + return createFrameworkTemplate({ + installation, + securityNotes: `**Best Practices:** +- Store endpoint and project ID in configuration +- Never commit API keys to version control +- Initialize the Appwrite client once and reuse` + }); };src/lib/utils/versions.js (1)
39-42: Consider usinggetCachedVersions()to avoid redundant API calls.
getSDKVersioncallsfetchSDKVersions()directly, bypassing the cache. If multiple SDK versions are fetched in sequence (e.g., when generating rules for multiple languages), each call triggers a separate API request.export async function getSDKVersion(sdkKey) { - const versions = await fetchSDKVersions(); + const versions = await getCachedVersions(); return versions[sdkKey] || 'latest'; }src/routes/+page.svelte (5)
21-26: Framework selection not updated on initial load.
updateFrameworks()is only called on SDK change events, but not during component initialization. If the defaultselectedSDK('javascript') doesn't have 'nextjs' as its first framework, the initialselectedFrameworkvalue could be invalid.Consider calling
updateFrameworks()on mount or using a reactive statement:+ import { onMount } from 'svelte'; + + onMount(() => { + updateFrameworks(); + }); + function updateFrameworks() { const sdk = SDK_OPTIONS[selectedSDK]; if (sdk && sdk.frameworks.length > 0) { selectedFramework = sdk.frameworks[0]; } }Or use Svelte's reactive statement:
$: if (SDK_OPTIONS[selectedSDK]) { const sdk = SDK_OPTIONS[selectedSDK]; if (sdk.frameworks.length > 0 && !sdk.frameworks.includes(selectedFramework)) { selectedFramework = sdk.frameworks[0]; } }
28-35: Missing error handling forgenerateRules.The
generatefunction doesn't handle potential errors fromgenerateRules(). If the async call fails, the user won't receive feedback.async function generate() { + try { generatedRules = await generateRules({ sdk: selectedSDK, framework: selectedFramework, features: selectedFeatures }); previewVisible = true; + } catch (err) { + console.error('Failed to generate rules:', err); + // Consider showing user feedback + } }
100-114: Allow at least one feature to be selected.Users can deselect all features, which may produce empty or invalid rules output. Consider enforcing a minimum selection.
function toggleFeature(featureId) { if (selectedFeatures.includes(featureId)) { + if (selectedFeatures.length === 1) { + return; // Prevent deselecting the last feature + } selectedFeatures = selectedFeatures.filter(f => f !== featureId); } else { selectedFeatures = [...selectedFeatures, featureId]; } }
150-153: Global style resets may cause unintended side effects.Using
:global(*)to disable tap-highlight affects all elements across the entire application. This could override styles in other components.Consider scoping this more narrowly or applying it only to interactive elements within this component:
.main-layout :global(*) { -webkit-tap-highlight-color: transparent; }
232-242: Potential accessibility issue with fixed viewport height.Using
max-height: 100vhandmin-height: 100vhwithoverflow: hiddenon.content-areamay cause content to be inaccessible on desktop if it exceeds viewport height and scrolling is disabled.The responsive styles do adjust this for smaller screens, but verify that content remains accessible on all desktop viewport sizes.
src/lib/languages/common/security.js (1)
48-61: Consider extracting duplicated best practices.The
frameworkNotes.angularandframeworkNotes.nodejsentries duplicate the base best practices text fromclientSecurity. This creates maintenance overhead if the base guidance changes.Consider composing from the base constants:
export const frameworkNotes = { angular: `${clientSecurity} - Use Angular services for dependency injection ${authNote}`, nodejs: `${clientSecurity} - Use environment variables for configuration - API keys grant admin access - use with extreme caution` };src/lib/languages/common/install.js (1)
5-11: Consider removing unused single-line install constants.The
npmInstall,yarnInstall,pnpmInstall, andbunInstallconstants appear to be unused, asjsInstall()generates a complete multi-package-manager installation block that is used throughout the codebase.If these are exported for potential future use or external consumption, consider documenting that intent. Otherwise, removing dead code improves maintainability.
src/lib/rules-generator.js (5)
5-11: UnusedSDKConfigproperties:importSyntax,exportSyntax,asyncSyntax.These properties are defined in the
SDKConfigtypedef and populated for each SDK but never referenced elsewhere in the codebase. If intended for future use, consider adding a TODO comment; otherwise, remove them to reduce maintenance burden.Also applies to: 19-91
104-124: Filter empty sections before joining to avoid extraneous blank lines.When features are not selected, empty strings in
sectionsare joined with\n\n, producing consecutive blank lines in the output.-${sections.join('\n\n')} +${sections.filter(Boolean).join('\n\n')}
152-169: Consider extracting the template resolution logic to reduce duplication.The "check if function and await" pattern is duplicated for both the framework-specific and vanilla fallback cases.
+async function resolveTemplate(template) { + if (typeof template === 'function') { + return await template(); + } + return template; +} + async function generateSDKInitialization(sdk, framework) { // ...templates definition... const sdkTemplates = templates[sdk]; if (sdkTemplates && sdkTemplates[framework]) { - const template = sdkTemplates[framework]; - if (typeof template === 'function') { - return await template(); - } - return template; + return await resolveTemplate(sdkTemplates[framework]); } if (sdkTemplates && sdkTemplates.vanilla) { - const template = sdkTemplates.vanilla; - if (typeof template === 'function') { - return await template(); - } - return template; + return await resolveTemplate(sdkTemplates.vanilla); } // ...fallback... }
182-197: Unusedsdkandframeworkparameters across all section generators.The
sdkandframeworkparameters are declared in all section generator functions (auth, database, storage, functions, messaging, sites, realtime) but never used. The generated content is identical regardless of SDK/framework. If SDK/framework-specific content is planned, consider adding a TODO; otherwise, remove the unused parameters.
183-183: Repeated dynamic imports of the same module could be consolidated.Each section generator dynamically imports
./languages/common/products.js. Since these run in parallel viaPromise.all, this causes redundant module resolution. Consider either:
- A single static import at the top of the file (simpler, no code-splitting benefit lost since all sections may be used)
- A shared cached import if code-splitting is intentional
+import { + authProductLinks, + databaseProductLinks, + storageProductLinks, + functionsProductLinks, + messagingProductLinks, + sitesProductLinks, + realtimeProductLinks +} from './languages/common/products.js'; -async function generateAuthSection(sdk, framework) { - const { authProductLinks } = await import('./languages/common/products.js'); +function generateAuthSection() { return `## Authentication & Teams // ... similar changes for other section generatorsAlso applies to: 205-205, 226-226, 246-246, 267-267, 288-288, 308-308
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlsrc/lib/assets/favicon.svgis excluded by!**/*.svg
📒 Files selected for processing (58)
.cursor/rules/APPWRITE.mdc(1 hunks).gitignore(1 hunks).npmrc(1 hunks).prettierignore(1 hunks).prettierrc(1 hunks)LICENSE(0 hunks)README.md(1 hunks)eslint.config.js(1 hunks)package.json(1 hunks)pnpm-workspace.yaml(1 hunks)src/app.d.ts(1 hunks)src/app.html(1 hunks)src/lib/appwrite.js(1 hunks)src/lib/languages/common/install.js(1 hunks)src/lib/languages/common/mcp.js(1 hunks)src/lib/languages/common/products.js(1 hunks)src/lib/languages/common/security.js(1 hunks)src/lib/languages/common/utils.js(1 hunks)src/lib/languages/dart/index.js(1 hunks)src/lib/languages/dart/server.js(1 hunks)src/lib/languages/dotnet/index.js(1 hunks)src/lib/languages/dotnet/server.js(1 hunks)src/lib/languages/dotnet/vanilla.js(1 hunks)src/lib/languages/go/index.js(1 hunks)src/lib/languages/go/server.js(1 hunks)src/lib/languages/index.js(1 hunks)src/lib/languages/js/angular.js(1 hunks)src/lib/languages/js/astro.js(1 hunks)src/lib/languages/js/index.js(1 hunks)src/lib/languages/js/nextjs.js(1 hunks)src/lib/languages/js/nodejs.js(1 hunks)src/lib/languages/js/nuxt.js(1 hunks)src/lib/languages/js/qwik.js(1 hunks)src/lib/languages/js/react.js(1 hunks)src/lib/languages/js/solid.js(1 hunks)src/lib/languages/js/svelte.js(1 hunks)src/lib/languages/js/tanstack.js(1 hunks)src/lib/languages/js/vanilla.js(1 hunks)src/lib/languages/js/vue.js(1 hunks)src/lib/languages/kotlin/index.js(1 hunks)src/lib/languages/php/index.js(1 hunks)src/lib/languages/php/server.js(1 hunks)src/lib/languages/python/flask.js(1 hunks)src/lib/languages/python/index.js(1 hunks)src/lib/languages/python/server.js(1 hunks)src/lib/languages/react-native/index.js(1 hunks)src/lib/languages/react-native/vanilla.js(1 hunks)src/lib/languages/ruby/index.js(1 hunks)src/lib/languages/ruby/server.js(1 hunks)src/lib/languages/swift/index.js(1 hunks)src/lib/rules-generator.js(1 hunks)src/lib/utils/versions.js(1 hunks)src/routes/+layout.svelte(1 hunks)src/routes/+page.svelte(1 hunks)static/robots.txt(1 hunks)svelte.config.js(1 hunks)tsconfig.json(1 hunks)vite.config.ts(1 hunks)
💤 Files with no reviewable changes (1)
- LICENSE
🧰 Additional context used
🧬 Code graph analysis (27)
src/lib/languages/python/server.js (7)
src/lib/languages/dotnet/server.js (2)
server(5-8)server(5-8)src/lib/languages/go/server.js (2)
server(5-8)server(5-8)src/lib/languages/php/server.js (2)
server(5-8)server(5-8)src/lib/languages/ruby/server.js (2)
server(5-8)server(5-8)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (2)
pythonInstall(54-66)pythonInstall(54-66)src/lib/languages/common/security.js (2)
serverSecurity(25-28)serverSecurity(25-28)
src/lib/languages/dart/server.js (4)
src/lib/utils/versions.js (1)
getSDKVersion(39-42)src/lib/languages/common/install.js (2)
dartInstall(129-147)dartInstall(129-147)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/security.js (2)
serverSecurity(25-28)serverSecurity(25-28)
src/lib/languages/js/vue.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (2)
clientSecurityWithEnv(17-20)clientSecurityWithEnv(17-20)
src/lib/languages/react-native/vanilla.js (3)
src/lib/languages/js/vanilla.js (2)
vanilla(5-8)vanilla(5-8)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)
src/lib/languages/js/angular.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (2)
frameworkNotes(48-61)frameworkNotes(48-61)
src/lib/languages/python/flask.js (1)
src/lib/languages/common/utils.js (1)
createSecuritySection(12-17)
src/lib/languages/ruby/server.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (2)
rubyInstall(93-105)rubyInstall(93-105)src/lib/languages/common/security.js (2)
serverSecurityWithConfig(34-37)serverSecurityWithConfig(34-37)
src/lib/languages/dart/index.js (4)
src/lib/languages/dart/server.js (2)
version(11-11)installation(12-12)src/lib/utils/versions.js (1)
getSDKVersion(39-42)src/lib/languages/common/install.js (2)
dartInstall(129-147)dartInstall(129-147)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)
src/lib/languages/js/solid.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (4)
clientSecurityWithEnv(17-20)clientSecurityWithEnv(17-20)authNote(42-43)authNote(42-43)
src/lib/languages/go/server.js (6)
src/lib/languages/dart/server.js (2)
server(10-14)server(10-14)src/lib/languages/php/server.js (2)
server(5-8)server(5-8)src/lib/languages/python/server.js (2)
server(5-8)server(5-8)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (2)
goInstall(82-88)goInstall(82-88)src/lib/languages/common/security.js (2)
serverSecurity(25-28)serverSecurity(25-28)
src/lib/languages/js/nuxt.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (2)
authNote(42-43)authNote(42-43)
svelte.config.js (1)
src/lib/rules-generator.js (1)
config(98-98)
src/lib/languages/js/react.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (2)
clientSecurity(8-11)clientSecurity(8-11)
src/lib/languages/js/tanstack.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (2)
authNote(42-43)authNote(42-43)
src/lib/languages/js/svelte.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (4)
clientSecurityWithEnv(17-20)clientSecurityWithEnv(17-20)authNote(42-43)authNote(42-43)
src/lib/languages/js/vanilla.js (4)
src/lib/languages/react-native/vanilla.js (2)
vanilla(4-10)vanilla(4-10)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (2)
clientSecurity(8-11)clientSecurity(8-11)
src/lib/languages/js/nodejs.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (2)
serverSecurity(25-28)serverSecurity(25-28)
src/lib/languages/swift/index.js (2)
src/lib/utils/versions.js (1)
getSDKVersion(39-42)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)
eslint.config.js (1)
src/lib/languages/js/svelte.js (2)
svelte(5-9)svelte(5-9)
src/lib/languages/common/utils.js (4)
src/lib/languages/dart/index.js (1)
installation(12-12)src/lib/languages/dart/server.js (1)
installation(12-12)src/lib/languages/kotlin/index.js (1)
installation(44-44)src/lib/languages/swift/index.js (1)
installation(33-33)
src/lib/languages/js/nextjs.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (4)
serverSecurity(25-28)serverSecurity(25-28)authNote(42-43)authNote(42-43)
src/lib/languages/common/install.js (4)
src/lib/languages/dart/index.js (1)
version(11-11)src/lib/languages/dart/server.js (1)
version(11-11)src/lib/languages/kotlin/index.js (1)
version(43-43)src/lib/languages/swift/index.js (1)
version(32-32)
src/lib/rules-generator.js (2)
src/lib/languages/common/mcp.js (1)
generateMCPRecommendation(10-54)src/lib/languages/common/products.js (14)
authProductLinks(16-28)authProductLinks(16-28)databaseProductLinks(33-41)databaseProductLinks(33-41)storageProductLinks(46-50)storageProductLinks(46-50)functionsProductLinks(55-61)functionsProductLinks(55-61)messagingProductLinks(66-74)messagingProductLinks(66-74)sitesProductLinks(79-103)sitesProductLinks(79-103)realtimeProductLinks(108-118)realtimeProductLinks(108-118)
src/lib/languages/dotnet/server.js (5)
src/lib/languages/go/server.js (2)
server(5-8)server(5-8)src/lib/languages/ruby/server.js (2)
server(5-8)server(5-8)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (2)
dotnetInstall(110-122)dotnetInstall(110-122)src/lib/languages/common/security.js (2)
serverSecurityWithConfig(34-37)serverSecurityWithConfig(34-37)
src/lib/languages/dotnet/vanilla.js (3)
src/lib/languages/js/vanilla.js (2)
vanilla(5-8)vanilla(5-8)src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (2)
dotnetInstall(110-122)dotnetInstall(110-122)
src/lib/languages/php/server.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (2)
phpInstall(71-77)phpInstall(71-77)src/lib/languages/common/security.js (2)
serverSecurity(25-28)serverSecurity(25-28)
src/lib/languages/js/astro.js (3)
src/lib/languages/common/utils.js (1)
createFrameworkTemplate(27-32)src/lib/languages/common/install.js (1)
jsInstall(18-44)src/lib/languages/common/security.js (4)
clientSecurityWithEnv(17-20)clientSecurityWithEnv(17-20)authNote(42-43)authNote(42-43)
🔇 Additional comments (55)
static/robots.txt (1)
1-3: robots.txt configuration looks good.The file correctly allows all crawlers to access all paths by default, which is the appropriate policy for a new public project. Syntax is valid per the robots.txt standard.
.npmrc (1)
1-1: Configuration is appropriate.Enforcing strict engine versions is a best practice for ensuring consistent environments across development and CI/CD pipelines.
.prettierrc (1)
1-17: Prettier configuration is well-structured.The config properly enables Svelte-aware formatting and establishes consistent conventions for the project. Parser override for .svelte files is correctly configured.
pnpm-workspace.yaml (1)
1-2: Verify monorepo intent for workspace configuration.The pnpm-workspace.yaml file indicates a monorepo setup, but only a single package.json is shown in this PR. Clarify whether the project is intended as a multi-package workspace or if this file can be removed to simplify the single-package configuration.
.prettierignore (1)
1-9: Ignore patterns are comprehensive.Lock files and static assets are correctly excluded from formatting, preventing unnecessary changes to generated or dependency-managed files.
package.json (1)
1-37: Package configuration is well-structured with comprehensive tooling.Scripts cover all essential workflows (dev, build, test, format, lint). Dependency selection is appropriate for a SvelteKit + TypeScript + ESLint + Prettier stack.
Verify that
@appwrite.io/[email protected]is the intended stable version. If this is a new or frequently-updated package, confirm it's not pinned to an outdated release.src/app.html (1)
1-12: HTML template is properly structured for SvelteKit.The template correctly implements SvelteKit placeholders, includes appropriate meta tags for viewport and theme configuration, and uses display: contents wrapper appropriately. The dark theme styling aligns with the Appwrite design system mentioned in package.json (@appwrite.io/pink).
.gitignore (1)
1-23: Gitignore patterns are comprehensive and appropriate.Coverage includes standard Node.js artifacts, SvelteKit build output, deployment platform directories, environment files with appropriate exceptions, and OS-specific metadata. The .env exclusion with .env.example and .env.test exceptions follows best practices for environment management.
src/app.d.ts (1)
1-13: LGTM!Standard SvelteKit type declaration scaffolding with placeholder interfaces for future augmentation.
eslint.config.js (1)
1-40: LGTM!Well-structured ESLint flat configuration with proper TypeScript and Svelte integration. Good practice including the justification comment for disabling
no-undef.src/lib/languages/go/index.js (1)
1-2: LGTM!Clean barrel export consistent with other language module patterns in the project.
src/lib/languages/ruby/index.js (1)
1-1: LGTM!Clean barrel export following the consistent pattern used across language modules.
svelte.config.js (1)
1-18: LGTM!Standard SvelteKit configuration with
adapter-autoandvitePreprocess. The inline comments appropriately document the adapter limitations and link to official docs for future reference.src/lib/languages/python/index.js (1)
1-2: LGTM!Clean barrel exports exposing both Flask-specific and generic server templates for Python.
src/lib/languages/php/index.js (1)
1-1: LGTM!Clean barrel export consistent with the pattern used across language modules.
vite.config.ts (1)
1-6: LGTM!Minimal and correct Vite configuration for SvelteKit. The
sveltekit()plugin handles all framework-specific build requirements.src/lib/languages/php/server.js (1)
1-8: LGTM!The PHP server template follows the established pattern consistently, using shared utilities for installation instructions and security notes.
src/routes/+layout.svelte (1)
1-13: LGTM!The layout component is clean and properly structured, using Svelte 5 runes syntax and correctly handling the favicon and theme imports.
src/lib/languages/go/server.js (1)
1-8: LGTM!The Go server template maintains consistency with other language server implementations, correctly composing shared utilities for installation and security guidance.
src/lib/languages/dotnet/index.js (1)
1-2: LGTM!Clean re-export pattern for aggregating .NET language modules.
src/lib/languages/python/server.js (1)
1-8: LGTM!The Python server template is consistent with other language server implementations, properly utilizing shared utilities for installation instructions and security notes.
src/lib/languages/common/mcp.js (1)
10-54: Documentation link verified as accessible and correct.The URL
https://appwrite.io/docs/tooling/mcp/cursorreturns HTTP 200, confirming the documentation link is valid and functional. The MCP recommendation content is comprehensive and well-structured with clear installation steps, configuration examples, and use cases.src/lib/languages/react-native/index.js (1)
1-1: LGTM!The re-export follows the established pattern used across other language modules in this PR.
tsconfig.json (1)
1-20: LGTM!The TypeScript configuration is well-structured for a SvelteKit project with strict type checking enabled and proper JS/TS interop to support the mixed .js and .ts modules throughout the codebase.
src/lib/languages/js/astro.js (1)
1-11: LGTM!The Astro template correctly composes installation instructions with appropriate security notes. The guidance to use separate clients for client-side and server-side operations is particularly relevant for Astro's hybrid rendering model.
src/lib/languages/js/angular.js (1)
1-8: LGTM!The Angular template follows the established pattern and uses framework-specific security notes that appropriately reference Angular services for dependency injection.
src/lib/languages/js/nextjs.js (1)
1-9: LGTM!The Next.js template correctly uses
serverSecuritynotes, which is appropriate given Next.js's server-first architecture and the need to emphasize API key protection.src/lib/languages/ruby/server.js (1)
1-8: LGTM!The Ruby server template correctly follows the established pattern for server-side SDK templates, using shared utilities for installation instructions and security notes. The inclusion of "Rails credentials" as an alternative to environment variables is appropriate for the Ruby ecosystem.
src/lib/languages/js/svelte.js (1)
1-9: LGTM!The Svelte template correctly uses the shared framework template pattern. The
.envfile reference and SSR auth note are appropriate for SvelteKit's conventions and SSR capabilities.src/lib/languages/js/react.js (1)
1-8: LGTM!The React template appropriately uses the generic
clientSecuritynotes without the SSR auth recommendation, which is correct since vanilla React is primarily client-side. SSR-specific guidance is correctly reserved for Next.js and similar frameworks.src/lib/languages/dotnet/server.js (1)
1-8: LGTM!The .NET server template follows the established pattern correctly. The "configuration files or environment variables" phrasing is appropriate for .NET's configuration patterns (e.g., appsettings.json, IConfiguration).
src/lib/languages/js/solid.js (1)
1-9: LGTM!The Solid template correctly mirrors the Svelte template structure, which is appropriate since both SolidStart and SvelteKit share similar SSR paradigms. The
.envfile reference and SSR auth note are well-suited for Solid's conventions.src/lib/languages/dart/server.js (1)
1-14: LGTM!Clean implementation that correctly:
- Fetches the server-dart SDK version asynchronously
- Passes
isServer=truetodartInstallto generate the correct pub command (dart pub get)- Uses
serverSecuritynotes appropriate for server-side SDK usagesrc/lib/languages/js/nuxt.js (2)
5-6: EnsurejsInstallis called, not passed as a reference.Comparing to other framework templates (e.g.,
tanstack.jsat line 6),jsInstall(...)is called with arguments to produce an installation string. Here,jsInstallappears to be passed directly without invocation.If
jsInstallDefaultis meant to be a pre-computed string constant (different from thejsInstallfunction), this is fine. Otherwise, you may need:export const nuxt = createFrameworkTemplate({ - installation: jsInstall, + installation: jsInstall(), securityNotes: `**Best Practices:**
1-1: The review comment is incorrect—jsInstallDefaultis a valid export.The verification confirms that
jsInstallDefaultis properly exported fromsrc/lib/languages/common/install.js(line 49) as the pre-computed result of callingjsInstall(). The import innuxt.jsis correct and functional. No action needed.Likely an incorrect or invalid review comment.
src/lib/languages/swift/index.js (1)
9-24: LGTM on the installation template.The
generateInstallationTemplatefunction provides clear instructions for both Swift Package Manager and Xcode integration, with proper version interpolation.src/lib/languages/js/tanstack.js (1)
1-16: LGTM!Well-structured TanStack Query integration template that:
- Installs both required packages (
appwriteand@tanstack/react-query) together- Provides TanStack-specific best practices (query keys, invalidation,
enabledoption)- Links to official documentation for further guidance
- Includes the shared
authNotefor SSR authentication recommendationssrc/lib/languages/js/nodejs.js (1)
1-9: LGTM!Clean implementation following the established pattern for JS framework templates. The additional security note about never logging API keys in error messages is a good server-specific practice.
src/lib/languages/dart/index.js (1)
1-25: LGTM!Well-structured module with proper async handling for version fetching. The
vanillaalias for backwards compatibility is a thoughtful addition, and the re-export pattern forserverkeeps the public API clean.src/lib/utils/versions.js (2)
5-32: LGTM!Good defensive coding with fallback versions when the API is unavailable. The error logging provides visibility into failures.
44-60: Cache implementation looks good, but it's currently unused.The caching mechanism is well-implemented. Once
getSDKVersionis updated to usegetCachedVersions(), this will prevent redundant API calls across the application.src/lib/languages/js/vanilla.js (2)
1-1: I'll help you verify this review comment. Let me start by checking ifjsInstallDefaultis actually exported from the install.js module and howjsInstallis being used.
<function_calls>
#!/bin/bashCheck for jsInstallDefault export in install.js
rg -n 'export.*jsInstallDefault' src/lib/languages/common/install.js
</function_calls>
<function_calls>
#!/bin/bashCheck all exports in install.js to understand what's available
rg -n '^export' src/lib/languages/common/install.js
</function_calls>
<function_calls>
#!/bin/bashCheck the usage of jsInstall in vanilla.js
cat -n src/lib/languages/js/vanilla.js
</function_calls>
<function_calls>
#!/bin/bashCheck how jsInstall is used in react-native/vanilla.js for comparison
cat -n src/lib/languages/js/react-native/vanilla.js
</function_calls>
5-8: The code is correct.jsInstallis an alias for the pre-computed stringjsInstallDefault.The import at line 1 shows
import { jsInstallDefault as jsInstall }, sojsInstallin this file is actually the result of calling thejsInstall()function with default arguments (line 49 in install.js). It's a string constant, not a function reference, so no invocation is needed.src/routes/+page.svelte (3)
37-47: LGTM!The
downloadRulesfunction correctly creates a blob, triggers download, cleans up the anchor element, and revokes the object URL to prevent memory leaks.
49-63: LGTM!The
copyRulesfunction handles both success and error cases with appropriate user feedback and timeout reset.
65-72: LGTM!The
toggleFeaturefunction correctly uses immutable array operations to trigger Svelte reactivity.src/lib/languages/common/utils.js (2)
12-17: LGTM!Clean utility function with proper JSDoc documentation and sensible default value.
27-32: LGTM!The
createFrameworkTemplatefunction correctly composes installation and security sections with proper separation.src/lib/languages/js/index.js (1)
1-13: LGTM!Clean barrel file pattern for aggregating JavaScript framework modules. The named re-exports provide a convenient single import point.
src/lib/languages/common/security.js (4)
8-11: LGTM!Clear and actionable client-side security best practices.
17-20: LGTM!Good use of a parameterized function to customize the environment file reference.
25-28: LGTM!Server security notes appropriately emphasize the critical nature of API key protection.
34-37: LGTM!Flexible template function for server security with configurable configuration method.
src/lib/languages/common/install.js (1)
18-44: LGTM!The
jsInstallfunction provides good flexibility with sensible defaults and generates comprehensive multi-package-manager installation instructions.src/lib/languages/index.js (1)
1-10: Clean barrel file for language module consolidation.The re-export pattern is clean and idiomatic for ES modules. The
reactNativecamelCase naming appropriately maps the hyphenated folder name to a valid JavaScript identifier.
| import { getSDKVersion } from '$lib/utils/versions.js'; | ||
| import { createFrameworkTemplate } from '../common/utils.js'; | ||
| import { serverSecurity } from '../common/security.js'; | ||
|
|
||
| /** | ||
| * Generates the Kotlin SDK installation template with the latest version | ||
| * @param {string} version - The SDK version to use | ||
| * @returns {string} | ||
| */ | ||
| function generateInstallationTemplate(version) { | ||
| return `## SDK Installation | ||
|
|
||
| Add the Appwrite Kotlin SDK to your \`build.gradle.kts\`: | ||
|
|
||
| **Recommended: Specify exact version for stability** | ||
|
|
||
| \`\`\`kotlin | ||
| dependencies { | ||
| implementation("io.appwrite:sdk-for-kotlin:${version}") | ||
| } | ||
| \`\`\` | ||
|
|
||
| Or for Maven, add to \`pom.xml\`: | ||
|
|
||
| **Recommended: Specify exact version** | ||
|
|
||
| \`\`\`xml | ||
| <dependency> | ||
| <groupId>io.appwrite</groupId> | ||
| <artifactId>sdk-for-kotlin</artifactId> | ||
| <version>${version}</version> | ||
| </dependency> | ||
| \`\`\` | ||
| `; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the Kotlin SDK installation template with the latest version from Appwrite's API | ||
| * This is the main export used by the rules generator | ||
| * @returns {Promise<string>} | ||
| */ | ||
| export const vanilla = async () => { | ||
| const version = await getSDKVersion('server-kotlin'); | ||
| const installation = generateInstallationTemplate(version); | ||
| return createFrameworkTemplate({ installation, securityNotes: serverSecurity }); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, locate the rules-generator file to confirm it exists
fd -type f -name "rules-generator.js" src/
# Then examine its contents, especially around template invocation
if [ -f "src/lib/rules-generator.js" ]; then
wc -l src/lib/rules-generator.js
fiRepository: appwrite/rules
Length of output: 276
🏁 Script executed:
#!/bin/bash
# Read the full rules-generator.js file to inspect error handling
cat -n src/lib/rules-generator.jsRepository: appwrite/rules
Length of output: 13367
Error handling for async template invocation is missing and should be added.
The concern in the original review is valid. The generateRules() function at line 97-128 calls generateSDKInitialization() at line 101 without any try-catch or error handling. When generateSDKInitialization() invokes async template functions (lines 156, 166) like the Kotlin vanilla() export, any errors from getSDKVersion('server-kotlin') or network failures will propagate unhandled, causing the entire rule generation to fail.
Wrap the async template invocations and the generateRules() call in appropriate error handling (try-catch blocks or Promise error handlers) to gracefully handle network failures, API unavailability, and other failures during version fetching. This will improve resilience and provide better error diagnostics.
🤖 Prompt for AI Agents
In src/lib/languages/kotlin/index.js lines 1-46, the exported async vanilla()
calls getSDKVersion and can propagate network/async errors to callers; update
vanilla() to wrap the await getSDKVersion('server-kotlin') call in a try-catch,
handle failures by either returning a clear fallback installation template
(e.g., a template using a pinned or placeholder version and a note about version
retrieval failure) or rethrowing a new error with contextual message, and ensure
any caught errors are logged or annotated so callers can detect and handle the
failure gracefully.
There was a problem hiding this 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/lib/rules-generator.js (2)
131-175: SDK initialization lookup and fallbacks are well‑designed (optional micro‑refactor)The template resolution logic (framework → vanilla → generic text) is a nice, safe fallback chain and should behave well even when a new framework lacks a specific snippet.
If you expect
generateRulesto be called frequently, you might consider hoisting thetemplatesobject to module scope so it isn’t reallocated on everygenerateSDKInitializationcall, but this is a micro‑optimization and not required for correctness:-async function generateSDKInitialization(sdk, framework) { - /** @type {Record<string, Record<string, string | (() => Promise<string>)>>} */ - const templates = { +/** @type {Record<string, Record<string, string | (() => Promise<string>)>>} */ +const TEMPLATES = { javascript: codeExamples.js, 'react-native': codeExamples.reactNative, python: codeExamples.python, php: codeExamples.php, go: codeExamples.go, flutter: codeExamples.dart, swift: codeExamples.swift, kotlin: codeExamples.kotlin, ruby: codeExamples.ruby, dotnet: codeExamples.dotnet - }; - - const sdkTemplates = templates[sdk]; + }; + +async function generateSDKInitialization(sdk, framework) { + const sdkTemplates = TEMPLATES[sdk];
177-326: Section generators are consistent; consider sharing the products import + boilerplateAll feature section functions follow a consistent pattern and read well. The only noticeable repetition is:
- The identical
(sdk, framework)signature (currently unused in bodies).- Repeated dynamic imports of
./languages/common/products.js.- Repeated “Best Practices” section scaffolding.
If this starts to grow, you could DRY it up with a small helper that takes
{ heading, linksKey, bullets }and returns the markdown, and a single cached dynamic import for product links. For now, this is perfectly acceptable and clear as is.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/lib/rules-generator.js(1 hunks)
🔇 Additional comments (2)
src/lib/rules-generator.js (2)
1-17: Imports and JSDoc typedefs look solidModule imports are clear, and the JSDoc typedefs for
SDKConfigandGeneratorConfiggive good editor/TS tooling support without adding runtime overhead. No changes needed here.
19-91: SDK_OPTIONS structure is clear and extensibleThe
SDK_OPTIONSmap is well‑structured and gives you a single source of truth for SDK labels, supported frameworks, and syntax hints. This should work well for driving both the UI and the generator. Just keep this in sync with the templates inlanguages/index.jswhen adding new SDKs/frameworks; the runtime fallbacks ingenerateSDKInitializationwill protect you in the meantime.
| /** | ||
| * @param {GeneratorConfig} config | ||
| * @returns {Promise<string>} | ||
| */ | ||
| export async function generateRules(config) { | ||
| const { sdk, framework, features } = config; | ||
| const sdkInfo = SDK_OPTIONS[sdk]; | ||
|
|
||
| const sdkInit = await generateSDKInitialization(sdk, framework); | ||
|
|
||
| // Generate all sections in parallel | ||
| const sections = await Promise.all([ | ||
| features.includes('auth') ? generateAuthSection(sdk, framework) : Promise.resolve(''), | ||
| features.includes('database') ? generateDatabaseSection(sdk, framework) : Promise.resolve(''), | ||
| features.includes('storage') ? generateStorageSection(sdk, framework) : Promise.resolve(''), | ||
| features.includes('functions') ? generateFunctionsSection(sdk, framework) : Promise.resolve(''), | ||
| features.includes('messaging') ? generateMessagingSection(sdk, framework) : Promise.resolve(''), | ||
| features.includes('sites') ? generateSitesSection(sdk, framework) : Promise.resolve(''), | ||
| features.includes('realtime') ? generateRealtimeSection(sdk, framework) : Promise.resolve('') | ||
| ]); | ||
|
|
||
| let rules = `--- | ||
| description: You are an expert developer focused on building apps with Appwrite's ${sdkInfo?.name || sdk} SDK. | ||
| alwaysApply: false | ||
| --- | ||
|
|
||
| # Appwrite Development Rules | ||
|
|
||
| ${generateMCPRecommendation()} | ||
|
|
||
| ${sdkInit} | ||
| ${sections.join('\n\n')} | ||
| `; | ||
|
|
||
| return rules; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Harden features handling and simplify section generation
There’s a small robustness risk if config.features is ever undefined/non‑array: features.includes(...) will throw at runtime. Easy to guard inside generateRules:
-export async function generateRules(config) {
- const { sdk, framework, features } = config;
+export async function generateRules(config) {
+ const { sdk, framework } = config;
+ const features = Array.isArray(config.features) ? config.features : [];This keeps the public API forgiving and avoids accidental crashes if the caller omits features or passes something unexpected.
If you want to reduce a bit of duplication in the section list, you could also consider a small feature→generator map and filter on features.includes(feature) instead of embedding Promise.resolve('') placeholders, but that’s optional.
📝 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.
| /** | |
| * @param {GeneratorConfig} config | |
| * @returns {Promise<string>} | |
| */ | |
| export async function generateRules(config) { | |
| const { sdk, framework, features } = config; | |
| const sdkInfo = SDK_OPTIONS[sdk]; | |
| const sdkInit = await generateSDKInitialization(sdk, framework); | |
| // Generate all sections in parallel | |
| const sections = await Promise.all([ | |
| features.includes('auth') ? generateAuthSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('database') ? generateDatabaseSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('storage') ? generateStorageSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('functions') ? generateFunctionsSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('messaging') ? generateMessagingSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('sites') ? generateSitesSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('realtime') ? generateRealtimeSection(sdk, framework) : Promise.resolve('') | |
| ]); | |
| let rules = `--- | |
| description: You are an expert developer focused on building apps with Appwrite's ${sdkInfo?.name || sdk} SDK. | |
| alwaysApply: false | |
| --- | |
| # Appwrite Development Rules | |
| ${generateMCPRecommendation()} | |
| ${sdkInit} | |
| ${sections.join('\n\n')} | |
| `; | |
| return rules; | |
| } | |
| /** | |
| * @param {GeneratorConfig} config | |
| * @returns {Promise<string>} | |
| */ | |
| export async function generateRules(config) { | |
| const { sdk, framework } = config; | |
| const features = Array.isArray(config.features) ? config.features : []; | |
| const sdkInfo = SDK_OPTIONS[sdk]; | |
| const sdkInit = await generateSDKInitialization(sdk, framework); | |
| // Generate all sections in parallel | |
| const sections = await Promise.all([ | |
| features.includes('auth') ? generateAuthSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('database') ? generateDatabaseSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('storage') ? generateStorageSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('functions') ? generateFunctionsSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('messaging') ? generateMessagingSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('sites') ? generateSitesSection(sdk, framework) : Promise.resolve(''), | |
| features.includes('realtime') ? generateRealtimeSection(sdk, framework) : Promise.resolve('') | |
| ]); | |
| let rules = `--- | |
| description: You are an expert developer focused on building apps with Appwrite's ${sdkInfo?.name || sdk} SDK. | |
| alwaysApply: false | |
| --- | |
| # Appwrite Development Rules | |
| ${generateMCPRecommendation()} | |
| ${sdkInit} | |
| ${sections.join('\n\n')} | |
| `; | |
| return rules; | |
| } |
🤖 Prompt for AI Agents
In src/lib/rules-generator.js around lines 93 to 128, features is accessed with
features.includes(...) which will throw if config.features is undefined or not
an array; normalize features to a safe array (e.g. const featuresList =
Array.isArray(features) ? features : []) at the top of the function and use that
for checks. While updating, simplify section generation by creating a small
feature→generator map (e.g. [{ key: 'auth', fn: generateAuthSection }, ...]),
filter that map by featuresList.includes(key), then Promise.all over the
selected generator calls to produce sections (no Promise.resolve('')
placeholders).
…tion templates and quick start URLs
…otes with server-side guidelines
eldadfux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also need to improve the readme, explaining the file structure and inheritance mechanism between the different instructions, encouraging contribution, adding a template for issues and PRs.
I would add a test that runs on a few PRs and generate demo apps to verify the quality of the instructions. Could be phase 2 as well.
Maybe we should also educate the LLM about some common mistakes like not whitelisting your domain if you get CORS issues. We can check our stats around the most viewed Discord threads to see what come up most often.
I miss some general description of what Appwrite is at the start. Maybe using this also to have links to our different channels for human based support (Discord, X).
I would also print a version of this repo in the generated file for tracking and debugging user issues.
Do we need to generate this file a bit differently depending on the SDK? I think most follow a standard, so maybe we can just use that as instructions to how to actually use this generated file.
|
|
||
| ### Installation Steps | ||
|
|
||
| 1. **Open Cursor Settings** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how helpful it is to recommend this to the agent. I find it hard to see in what context it will use it to suggest it back to the end-user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of making this an opening recommendation simply because it helps to have access to exact examples. But we can leave this out and keep it as a recommendation in the docs
| export const clientSecurityWithEnv = (envFile = '.env.local') => `**Best Practices:** | ||
| - Store endpoint and project ID in environment variables (${envFile}) | ||
| - Never commit API keys to version control | ||
| - Initialize services once and export as singletons`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe same for the client. I also think maybe some examples on how to handle a sever and client instance of the SDKs can be helpful. I think one more crucial thing for the setup of the SDK is to explore or recommend on how to communicate between client and server SDK for SSR apps. Maybe how to generate a JWT, how refresh it etc.
|
|
||
| \`\`\`kotlin | ||
| dependencies { | ||
| implementation("io.appwrite:sdk-for-android:${version}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking of this again, should we just try to push to latest version? assuming the docs links we share also relevant for latest version all the time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For most SDKs, this isn't an issue. Some of them expect a version number though.
| /** | ||
| * Functions product documentation | ||
| */ | ||
| export const functionsProductLinks = `For detailed serverless function execution, see the [Functions Execution Documentation](https://appwrite.io/docs/products/functions/execute). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Develop page is really important for functions. Including links to some of our starter templates per language have been really crucial for me in getting functions to build and execute well after a single prompt generation. I think maybe we should also encourage the LLM to go this path only on specific use cases such as scheduled tasks, event driven tasks etc.
|
|
||
| For server-side rendering (SSR) authentication, see the [SSR Login Guide](https://appwrite.io/docs/products/auth/server-side-rendering). | ||
|
|
||
| For Teams management, team invitations, and team-based permissions, see the [Teams Documentation](https://appwrite.io/docs/products/auth/teams). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multi-tenancy should be a big topic, maybe we should cover it under permissions. It's really important and we don't cover it enough even in our own docs. Its crucial the LLM prefer team/member based roles of specific user based roles and then understand how to do member management from scratch.
…js generation script; include MCP in framework options
There was a problem hiding this 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
♻️ Duplicate comments (3)
src/lib/rules-generator.js (1)
112-145: Harden features parameter handlingIf
config.featuresisundefinedor not an array, thefeatures.includes(...)calls will throw a runtime error. Consider normalizing at the start of the function for robustness.Apply this diff:
export async function generateRules(config) { - const { sdk, framework, features, includeMCP = false } = config; + const { sdk, framework, includeMCP = false } = config; + const features = Array.isArray(config.features) ? config.features : []; const sdkInfo = SDK_OPTIONS[sdk];src/lib/languages/common/products.js (2)
6-11: Address duplicate documentation linksThe rows documentation link (line 9) appears again at line 33, and the storage link (line 11) reappears at lines 46 and 48. Consider removing these from
commonProductLinkssince they're already covered in their respective product sections.
16-18: Remove duplicate Quick Start Guide linkThe Authentication Quick Start Guide link appears on both line 16 and line 18. Keep only one reference to avoid duplication.
🧹 Nitpick comments (3)
scripts/lib-loader.js (1)
10-18: Consider adding existence check for clearer error messages.While Node.js will error if the resolved file doesn't exist, adding an explicit check could provide clearer diagnostics during development.
if (specifier.startsWith('$lib/')) { const relativePath = specifier.replace('$lib/', ''); const absolutePath = resolvePath(projectRoot, 'src', 'lib', relativePath); + // Optional: Add existence check using fs.existsSync for better error messages const fileUrl = pathToFileURL(absolutePath).href; return { url: fileUrl, format: 'module', shortCircuit: true }; }src/routes/+page.svelte (1)
86-88: Add keys to each blocks for better performanceSvelte recommends adding keys to each blocks to optimize rendering and prevent potential issues when lists change.
Apply these diffs:
-{#each Object.entries(SDK_OPTIONS) as [key, value]} +{#each Object.entries(SDK_OPTIONS) as [key, value] (key)} <option value={key}>{value.name}</option> {/each}-{#each SDK_OPTIONS[selectedSDK]?.frameworks || [] as framework} +{#each SDK_OPTIONS[selectedSDK]?.frameworks || [] as framework (framework)} <option value={framework}>{framework.charAt(0).toUpperCase() + framework.slice(1)}</option> {/each}-{#each features as feature} +{#each features as feature (feature.id)} <label class="checkbox"> <input type="checkbox" checked={selectedFeatures.includes(feature.id)} on:change={() => toggleFeature(feature.id)} /> <span>{feature.label}</span> </label> {/each}Also applies to: 95-97, 104-113
src/lib/rules-generator.js (1)
201-201: Consider prefixing unused parameters with underscoreSeveral section generator functions have
sdkandframeworkparameters that aren't currently used. If these are reserved for future framework-specific customization, prefix them with underscores to indicate intentional non-use and silence linter warnings.Example:
-async function generateAuthSection(sdk, framework) { +async function generateAuthSection(_sdk, _framework) {Note:
generateFunctionsSectiondoes use thesdkparameter (line 719), so it should not be changed.Also applies to: 234-234, 622-622, 648-648, 755-755, 776-776, 796-796
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/lib/assets/favicon.svgis excluded by!**/*.svg
📒 Files selected for processing (7)
package.json(1 hunks)scripts/generate-nextjs-rules.js(1 hunks)scripts/lib-loader.js(1 hunks)src/lib/languages/common/mcp.js(1 hunks)src/lib/languages/common/products.js(1 hunks)src/lib/rules-generator.js(1 hunks)src/routes/+page.svelte(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- package.json
🧰 Additional context used
🧬 Code graph analysis (2)
scripts/lib-loader.js (1)
scripts/generate-nextjs-rules.js (1)
__dirname(7-7)
scripts/generate-nextjs-rules.js (2)
scripts/lib-loader.js (1)
__dirname(6-6)src/lib/rules-generator.js (2)
rules(133-142)generateRules(112-145)
🪛 ESLint
src/lib/rules-generator.js
[error] 201-201: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 201-201: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 234-234: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 234-234: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 622-622: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 622-622: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 648-648: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 648-648: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 717-717: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 755-755: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 755-755: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 776-776: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 776-776: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 796-796: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 796-796: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
src/routes/+page.svelte
[error] 86-88: Each block should have a key
(svelte/require-each-key)
[error] 95-97: Each block should have a key
(svelte/require-each-key)
[error] 104-113: Each block should have a key
(svelte/require-each-key)
🔇 Additional comments (12)
scripts/lib-loader.js (2)
1-7: LGTM! Clean ESM-compatible path setup.The imports and path resolution are appropriate for a custom ESM loader. The use of
import.meta.urlto derive__dirnameis the correct approach for ES modules.
9-21: I'll help you verify the review comment about$libimports and file extensions in the loader. Let me search the codebase for actual usage patterns.
<function_calls>
#!/bin/bashFind all files that import from $lib/
rg -n "$lib/" --type=js --type=ts --type=mjs --type=cjs -A 2 -B 2 | head -100
</function_calls>Let me also check the repository structure to better understand the project:
<function_calls>
#!/bin/bashGet overview of repository structure
git ls-files | head -30
</function_calls>Let me search more specifically for imports with the $lib alias:
<function_calls>
#!/bin/bashSearch for any import or require statements using $lib
echo "=== Looking for $lib imports in various file types ==="
rg "from ['"]?\$lib|require(['\"]\$lib" --type=js --type=ts --type=mjs -n | head -50echo ""
echo "=== Checking if lib-loader is being used ==="
rg "lib-loader|--experimental-loader" . --type=js --type=json --type=mjs -n | head -20
</function_calls>Let me check the loader file itself and its context:
<function_calls>
#!/bin/bashRead the lib-loader.js file to understand its purpose
echo "=== Contents of scripts/lib-loader.js ==="
cat -n scripts/lib-loader.jsecho ""
echo "=== Check for package.json or similar configuration ==="
cat -n package.json 2>/dev/null | grep -A 5 -B 5 "loader|exports" || echo "No relevant package.json config found"echo ""
echo "=== Look for any test or example files using the loader ==="
find . -type f ( -name ".md" -o -name ".mjs" -o -name "*.json" ) | xargs grep -l "$lib|lib-loader" 2>/dev/null | head -10
</function_calls>Let me take a more targeted approach:
<function_calls>
#!/bin/bashFirst, verify the file exists and show its content
ls -lah scripts/lib-loader.js 2>/dev/null && echo "File found" || echo "File not found"
echo ""
Show the file
head -30 scripts/lib-loader.js
echo ""
Search for any reference to lib-loader or $lib in the entire repo
echo "=== References to lib-loader ==="
rg "lib-loader" . -n 2>/dev/null || echo "No references to lib-loader found"echo ""
echo "=== Any Node.js loader configuration ==="
rg "node.--loader|node.--experimental-loader" . -n -t js -t json 2>/dev/null || echo "No loader configuration found"
</function_calls>scripts/generate-nextjs-rules.js (1)
1-32: LGTM!The script is well-structured with proper error handling, clear console output, and comprehensive feature generation. The output path to the parent directory appears intentional for a generator script that produces distribution files.
src/lib/languages/common/mcp.js (1)
10-54: LGTM!The MCP recommendation content is comprehensive and well-structured. The installation steps are clear, and the benefits section provides good examples of use cases.
src/routes/+page.svelte (2)
50-64: LGTM!Good error handling for clipboard operations with clear user feedback via the button text state.
151-452: LGTM!Comprehensive responsive design with good mobile and touch device support. The styles are well-organized with appropriate breakpoints.
src/lib/rules-generator.js (6)
153-194: LGTM!The SDK initialization logic has proper fallbacks (framework-specific → vanilla → generic) and correctly handles both synchronous and asynchronous templates.
201-227: LGTM!The authentication section provides comprehensive best practices with strong emphasis on team-based architecture and multi-tenancy, addressing the need for robust member management patterns.
234-615: Excellent multi-tenancy guidance!This section provides exceptional depth on multi-tenancy patterns, team-based permissions, and member management. The step-by-step implementation patterns and code examples will be highly valuable for developers building secure, scalable applications.
672-710: LGTM!The function template helpers provide direct links to official starter templates, which addresses the need for developers to have access to properly configured function scaffolds.
717-748: LGTM!The functions section appropriately emphasizes when to use starter templates, particularly for scheduled tasks and event-driven functions, which ensures developers get the correct project structure and configuration.
796-814: LGTM!The realtime section provides comprehensive best practices for subscription management, including proper cleanup patterns and connection handling.
| async function generate() { | ||
| generatedRules = await generateRules({ | ||
| sdk: selectedSDK, | ||
| framework: selectedFramework, | ||
| features: selectedFeatures | ||
| }); | ||
| previewVisible = true; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MCP feature selection not working
The generate() function doesn't pass the includeMCP parameter to generateRules(). When users check the MCP checkbox, it adds 'mcp' to selectedFeatures, but this isn't converted to the includeMCP boolean that generateRules() expects.
Apply this diff to fix the issue:
async function generate() {
+ const includeMCP = selectedFeatures.includes('mcp');
+ const productFeatures = selectedFeatures.filter(f => f !== 'mcp');
+
generatedRules = await generateRules({
sdk: selectedSDK,
framework: selectedFramework,
- features: selectedFeatures
+ features: productFeatures,
+ includeMCP
});
previewVisible = true;
}🤖 Prompt for AI Agents
In src/routes/+page.svelte around lines 29 to 36, the generate() call fails to
provide the includeMCP boolean to generateRules; compute includeMCP as
selectedFeatures.includes('mcp') and call generateRules with includeMCP set to
that value, and pass features as selectedFeatures without the 'mcp' token (e.g.,
features: selectedFeatures.filter(f => f !== 'mcp')) so the MCP flag is conveyed
correctly and the features list remains valid.
…rite Cursor Rules Generator; add .mdc file extension to .gitignore
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.gitignore(1 hunks)README.md(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- .gitignore
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
README.md
89-89: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (3)
README.md (3)
1-36: Documentation is comprehensive and well-structured.The README clearly describes the Cursor Rules Generator's features, supported SDKs/frameworks, and provides a well-organized table summarizing SDK-to-framework mappings. The introductory section accurately reflects the PR objectives.
38-86: Getting Started and Development sections are clear and actionable.Installation steps, development scripts, and usage flow are well-documented and include appropriate prerequisites. The available scripts and their purposes are clearly listed for developer reference.
109-130: Extension guidelines are helpful for contributors.The instructions for adding new SDKs, frameworks, and features provide clear steps and reference the relevant files, making it easy for future contributors to extend the tool.
| ``` | ||
| appwrite-cursor-rules/ | ||
| ├── src/ | ||
| │ ├── lib/ | ||
| │ │ ├── languages/ # SDK and framework-specific code examples | ||
| │ │ │ ├── js/ # JavaScript/TypeScript frameworks | ||
| │ │ │ ├── python/ # Python frameworks | ||
| │ │ │ ├── common/ # Shared rules (products, MCP, etc.) | ||
| │ │ │ └── ... # Other SDKs | ||
| │ │ ├── rules-generator.js # Main rules generation logic | ||
| │ │ └── utils/ # Utility functions | ||
| │ └── routes/ | ||
| │ ├── +page.svelte # Main application page | ||
| │ └── +layout.svelte # Layout component | ||
| ├── scripts/ | ||
| │ ├── generate-nextjs-rules.js # Example script for generating rules | ||
| │ └── lib-loader.js # Module loader for scripts | ||
| └── static/ # Static assets | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify a language for the fenced code block.
The project structure code block at line 89 should include a language identifier for proper markdown linting compliance.
Apply this diff to add a language specifier:
-```
+```
appwrite-cursor-rules/
├── src/
│ ├── lib/
│ │ ├── languages/ # SDK and framework-specific code examples
│ │ │ ├── js/ # JavaScript/TypeScript frameworks
│ │ │ ├── python/ # Python frameworks
│ │ │ ├── common/ # Shared rules (products, MCP, etc.)
│ │ │ └── ... # Other SDKs
│ │ ├── rules-generator.js # Main rules generation logic
│ │ └── utils/ # Utility functions
│ └── routes/
│ ├── +page.svelte # Main application page
│ └── +layout.svelte # Layout component
├── scripts/
│ ├── generate-nextjs-rules.js # Example script for generating rules
│ └── lib-loader.js # Module loader for scripts
└── static/ # Static assetsSince the content is a directory tree rather than executable code, you may alternatively use a backtick fence without a language identifier if your markdown configuration permits it, or use txt as the language.
Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
89-89: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
README.md around lines 89 to 107: the fenced code block containing the project
directory tree lacks a language identifier which fails markdown linting; update
the opening fence from ``` to ```txt (or another appropriate identifier such as
text) so the block is explicitly marked as plain text, leaving the content
unchanged and keeping the closing ``` intact.
…ance code snippets for multi-tenancy best practices and member management flows.
There was a problem hiding this 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/lib/rules-generator.js (1)
108-145: Hardenfeatureshandling to prevent runtime errors.The past review comment correctly identified that
features.includes(...)on lines 121-128 will throw ifconfig.featuresisundefinedor not an array. This issue remains unaddressed.As suggested in the previous review, normalize
featuresat the beginning of the function:export async function generateRules(config) { - const { sdk, framework, features, includeMCP = false } = config; + const { sdk, framework, includeMCP = false } = config; + const features = Array.isArray(config.features) ? config.features : []; const sdkInfo = SDK_OPTIONS[sdk];This defensive approach keeps the API forgiving and prevents crashes if callers omit or mistype
features.
🧹 Nitpick comments (1)
src/lib/rules-generator.js (1)
196-227: Consider prefixing unused parameters with underscores.ESLint is flagging unused parameters in several section generator functions. While the consistent
(sdk, framework)signature across all generators is intentional for thePromise.allcall on line 120, you can satisfy the linter by prefixing unused parameters with underscores:Functions with unused parameters:
generateAuthSection(line 201): bothsdkandframeworkunusedgeneratePermissionsSection(line 234):frameworkunusedgenerateDatabaseSection(line 500): both unusedgenerateStorageSection(line 526): both unusedgenerateFunctionsSection(line 595):frameworkunusedgenerateMessagingSection(line 633): both unusedgenerateSitesSection(line 654): both unusedgenerateRealtimeSection(line 674): both unusedExample refactor for
generateAuthSection:-async function generateAuthSection(sdk, framework) { +async function generateAuthSection(_sdk, _framework) { const { authProductLinks } = await import('./languages/common/products.js');Apply the same pattern to other functions, prefixing only the parameters that remain unused.
Also applies to: 229-469, 495-519, 521-543, 590-626, 628-647, 649-667, 669-692
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/lib/rules-generator.js(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/lib/rules-generator.js (2)
src/lib/languages/common/mcp.js (1)
generateMCPRecommendation(10-54)src/lib/languages/common/products.js (14)
authProductLinks(16-28)authProductLinks(16-28)databaseProductLinks(33-41)databaseProductLinks(33-41)storageProductLinks(46-50)storageProductLinks(46-50)functionsProductLinks(55-61)functionsProductLinks(55-61)messagingProductLinks(66-74)messagingProductLinks(66-74)sitesProductLinks(79-103)sitesProductLinks(79-103)realtimeProductLinks(108-118)realtimeProductLinks(108-118)
🪛 ESLint
src/lib/rules-generator.js
[error] 201-201: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 201-201: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 234-234: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 500-500: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 500-500: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 526-526: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 526-526: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 595-595: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 633-633: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 633-633: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 654-654: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 654-654: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 674-674: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 674-674: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
|
@adityaoberai another cool idea would be to make this generator accessible via an API that returns the relevant markdown version |
There was a problem hiding this 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
♻️ Duplicate comments (1)
README.md (1)
177-200: Add a language identifier to the project-structure code fence.markdownlint (MD040) flags this block because the fenced code block has no language. Since this is a directory tree, using
txt(or similar) satisfies the rule without affecting rendering.-``` +```txt appwrite-cursor-rules/ ├── src/ │ ├── lib/ │ │ ├── languages/ # SDK and framework-specific code examples │ │ │ ├── js/ # JavaScript/TypeScript frameworks │ │ │ ├── python/ # Python frameworks │ │ │ ├── common/ # Shared rules (products, MCP, etc.) │ │ │ └── ... # Other SDKs │ │ ├── rules-generator.js # Main rules generation logic │ │ └── utils/ # Utility functions │ └── routes/ │ ├── api/ │ │ ├── rules/ │ │ │ └── +server.js # API endpoint for generating rules │ │ └── sdks/ │ │ └── +server.js # API endpoint for listing SDKs │ ├── +page.svelte # Main application page │ └── +layout.svelte # Layout component ├── scripts/ │ ├── generate-nextjs-rules.js # Example script for generating rules │ └── lib-loader.js # Module loader for scripts └── static/ # Static assets
🧹 Nitpick comments (3)
README.md (1)
130-133: Capitalize “Markdown” in prose for consistency with tooling.LanguageTool flags “markdown text” as a common noun; using “Markdown text” reads better and keeps terminology consistent.
-- Returns the generated rules as markdown text +- Returns the generated rules as Markdown textsrc/routes/api/sdks/+server.js (1)
4-7: Remove or fix the stale JSDoc@paramforGET.The JSDoc documents a
Requestparameter, butGETcurrently takes no arguments, which can mislead readers and tooling.If you don’t need the event/request object, you can drop the JSDoc block:
-/** - * @param {Request} request - */ -export async function GET() { +export async function GET() {src/routes/api/rules/+server.js (1)
7-17: HardennormalizeFeaturesto trim and ignore unknown feature names.Right now, any unknown
featuresvalues (e.g.features=foo,bar) pass through and result in no feature sections being generated, without signaling an issue. You can make this more robust by trimming inputs and discarding unsupported names while still honoring the specialallalias.For example:
-/** - * Normalize features array - replace 'all' with all available features - * @param {string[]} features - * @returns {string[]} - */ -function normalizeFeatures(features) { - if (features.includes('all')) { - return ALL_FEATURES; - } - return features; -} +/** + * Normalize features: + * - trims values + * - discards unknown feature names + * - replaces 'all' with ALL_FEATURES + * @param {string[]} features + * @returns {string[]} + */ +function normalizeFeatures(features) { + const cleaned = features + .map((feature) => feature.trim()) + .filter((feature) => ALL_FEATURES.includes(feature) || feature === 'all'); + + if (cleaned.includes('all')) { + return ALL_FEATURES; + } + + return cleaned; +}This keeps the API forgiving while avoiding silently ignored typos.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
README.md(1 hunks)src/routes/api/rules/+server.js(1 hunks)src/routes/api/sdks/+server.js(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/routes/api/sdks/+server.js (1)
src/routes/api/rules/+server.js (1)
GET(22-84)
src/routes/api/rules/+server.js (2)
src/routes/api/sdks/+server.js (1)
GET(7-35)src/lib/rules-generator.js (1)
generateRules(112-145)
🪛 LanguageTool
README.md
[uncategorized] ~132-~132: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...utf-8- Returns the generated rules as markdown text - IncludesContent-Disposition` h...
(MARKDOWN_NNP)
🪛 markdownlint-cli2 (0.18.1)
README.md
177-177: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (2)
src/routes/api/sdks/+server.js (1)
9-30: SDK listing and feature metadata JSON shape looks good.The transformation of
SDK_OPTIONSinto{ id, name, frameworks, importSyntax, exportSyntax, asyncSyntax }plus theavailableFeaturesarray is straightforward and matches how the README describes this endpoint.src/routes/api/rules/+server.js (1)
22-83: Query parsing, validation, and response formats are coherent and match the documented API.The GET handler’s flow—defaulting
sdk/framework, validating againstSDK_OPTIONS, normalizingfeatures, delegating togenerateRules, and switching between JSON vs Markdown attachment based onformat—is clear and lines up with the README examples and error codes.
| **Response:** | ||
| ```json | ||
| { | ||
| "sdks": [ | ||
| { | ||
| "id": "javascript", | ||
| "name": "JavaScript/TypeScript", | ||
| "frameworks": ["nextjs", "react", "vue", ...], | ||
| "importSyntax": "import", | ||
| "exportSyntax": "export", | ||
| "asyncSyntax": "async/await" | ||
| }, | ||
| ... | ||
| ], | ||
| "availableFeatures": ["auth", "database", "storage", "functions", "messaging", "sites", "realtime"] | ||
| } | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align /api/sdks response example with actual API (availableFeatures includes "all").
src/routes/api/sdks/+server.js returns availableFeatures including the special "all" value, but the README example omits it. This can confuse API consumers about the supported features values.
Consider updating the example to include "all":
- "availableFeatures": ["auth", "database", "storage", "functions", "messaging", "sites", "realtime"]
+ "availableFeatures": ["auth", "database", "storage", "functions", "messaging", "sites", "realtime", "all"]🤖 Prompt for AI Agents
In README.md around lines 85 to 101, the example JSON for the /api/sdks response
omits the special "all" value returned by the real API; update the example
response to include "all" in the availableFeatures array (e.g.,
["auth","database","storage","functions","messaging","sites","realtime","all"])
so the docs match src/routes/api/sdks/+server.js.
There was a problem hiding this 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
♻️ Duplicate comments (1)
src/lib/rules-generator.js (1)
112-129: Normalizefeaturesbefore calling.includesand consider simplifying section assembly
generateRulesassumesconfig.featuresis a defined array; if it’s everundefinedor non‑array, everyfeatures.includes(...)call will throw at runtime. To make the API more forgiving, normalizefeaturesup front and use that for checks. You can also drop the explicitPromise.resolve('')placeholders by driving sections from a small descriptor list.Example refactor:
-export async function generateRules(config) { - const { sdk, framework, features, includeMCP = false } = config; +export async function generateRules(config) { + const { sdk, framework, includeMCP = false } = config; + const features = + Array.isArray(config.features) ? config.features : []; @@ - // Generate all sections in parallel - // Permissions section is mandatory for all products - const sections = await Promise.all([ - features.includes('auth') ? generateAuthSection(sdk, framework) : Promise.resolve(''), - generatePermissionsSection(sdk, framework), - features.includes('database') ? generateDatabaseSection(sdk, framework) : Promise.resolve(''), - features.includes('storage') ? generateStorageSection(sdk, framework) : Promise.resolve(''), - features.includes('functions') ? generateFunctionsSection(sdk, framework) : Promise.resolve(''), - features.includes('messaging') ? generateMessagingSection(sdk, framework) : Promise.resolve(''), - features.includes('sites') ? generateSitesSection(sdk, framework) : Promise.resolve(''), - features.includes('realtime') ? generateRealtimeSection(sdk, framework) : Promise.resolve('') - ]); + // Generate all sections in parallel + const sectionSpecs = [ + { key: 'auth', fn: generateAuthSection }, + { key: 'permissions', fn: generatePermissionsSection, always: true }, + { key: 'database', fn: generateDatabaseSection }, + { key: 'storage', fn: generateStorageSection }, + { key: 'functions', fn: generateFunctionsSection }, + { key: 'messaging', fn: generateMessagingSection }, + { key: 'sites', fn: generateSitesSection }, + { key: 'realtime', fn: generateRealtimeSection } + ]; + + const sections = await Promise.all( + sectionSpecs + .filter(({ key, always }) => always || features.includes(key)) + .map(({ fn }) => fn(sdk, framework)) + );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/lib/rules-generator.js(1 hunks)
🧰 Additional context used
🪛 ESLint
src/lib/rules-generator.js
[error] 201-201: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 201-201: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 234-234: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 500-500: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 500-500: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 526-526: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 526-526: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 595-595: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 633-633: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 633-633: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 654-654: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 654-654: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 674-674: 'sdk' is defined but never used.
(@typescript-eslint/no-unused-vars)
[error] 674-674: 'framework' is defined but never used.
(@typescript-eslint/no-unused-vars)

What does this PR do?
Create a Cursor Rules Generator
Test Plan
Visit the preview deployment
Related PRs and Issues
No
Have you read the Contributing Guidelines on issues?
Yes
Summary by CodeRabbit
New Features
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.