Development guidelines for CardTool.app - a Next.js 16 credit card rewards tracking app with Supabase, Clerk auth, and strict database migration workflows
Development guidelines for the CardTool.app credit card rewards tracking application.
CardTool.app is a Next.js 16 application for tracking credit card rewards and benefits, built with:
When creating or modifying database schema:
1. **Create migration file** in `supabase/migrations/` directory
2. **Update TypeScript types** in `src/lib/database.types.ts` in the SAME commit
3. **Enable RLS on all new tables** (see RLS section)
4. **Run migration using Supabase MCP tools** (see below)
5. **Verify migration success** by querying affected tables
Use Supabase MCP server tools - do NOT instruct users to run SQL manually:
```typescript
// Execute SQL directly
CallMcpTool(
server: "user-supabase",
toolName: "execute_sql",
arguments: {"query": "ALTER TABLE cards ADD COLUMN brand text;"}
)
// Or apply a full migration file
CallMcpTool(
server: "user-supabase",
toolName: "apply_migration",
arguments: {"migration_file": "path/to/migration.sql"}
)
```
For complex migrations, break into smaller `execute_sql` calls to avoid errors.
**ALL tables must have RLS enabled**, even though the app uses service role key (bypasses RLS). This provides defense-in-depth.
For tables with `user_id` column:
```sql
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can manage their own data"
ON table_name FOR ALL TO authenticated
USING (user_id = (auth.jwt()->>'sub'))
WITH CHECK (user_id = (auth.jwt()->>'sub'));
```
For shared read-only data (e.g., `cards`, `issuers`):
```sql
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Authenticated users can read table_name"
ON table_name FOR SELECT TO authenticated
USING (true);
```
For admin/internal tables (e.g., `stripe_members`):
```sql
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
-- NO policies added - blocks all non-service-role access
```
- Backgrounds: `zinc-900`, `zinc-950`
- Text: `zinc-300`, `zinc-400`
1. **NEVER** use `new Date(dateString)` for date-only strings → use `parseLocalDate()`
2. **NEVER** use `date.toISOString().split('T')[0]` for local dates → use `formatDateToString()`
3. **NEVER** duplicate date utilities in components → import from `@/lib/utils`
4. For ISO strings with time, extract date directly: `str.substring(0, 10)` or `extractDateFromISO()`
`new Date("2024-01-15")` parses as UTC midnight, causing ±1 day errors in US timezones. Similarly, `toISOString()` converts to UTC. Always use the centralized utilities to avoid timezone bugs.
1. **NEVER commit/push to main** unless user explicitly instructs for THAT SPECIFIC change
2. A "push" instruction applies ONLY to the changes discussed at that moment, NOT future changes
3. **Always run `npm run build`** and verify it passes before any commit
4. After bug fixes or changes, **ALWAYS ask "Ready to push?"** before pushing
5. **When in doubt, ask first**
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/cursor-rules-for-cardtoolapp/raw