VibeWeek
Home/Grow/Saved Views & Saved Filters

Saved Views & Saved Filters

⬅️ Day 6: Grow Overview

If you're building B2B SaaS in 2026 with data tables / lists / dashboards, power users want to save filter combinations as named views — "My open tickets", "Q3 enterprise deals", "High-priority bugs". Linear, Notion, Airtable, Asana, GitHub Projects all have them. The naive approach: filters reset on every page load. The structured approach: save view-state as named entities, share with team, set defaults, support per-user customization, sync via URL. Saved views graduate a product from "useful" to "indispensable" — once users build their workflow around saved views, they don't leave. This guide covers the implementation craft. (Related: data-tables-sort-filter-bulk-chat for filter mechanics; this is for saving / managing filters.)

1. Decide view scope — personal, shared, or both

Decide view scope.

Personal views (my views):
- Created by user; visible to user only
- Each team member has own views
- Most flexible

Shared views (team views):
- Created and shared
- All members see same view
- "Open bugs" - team-shared

Workspace views:
- Set by admin; default for all members
- Standard reports

Hybrid (recommended):
- Personal views by default
- "Share with team" toggle to make shared
- Admin can mark default workspace views

For [USE CASE]:

Linear pattern:
- Personal views by default
- Shared workspace views possible
- Default views per team

Notion pattern:
- Database views shared by default
- Each user can customize their own version
- Confusing to onboard

Airtable pattern:
- Personal vs shared views distinct
- Permissions per view

Recommendation:
- Personal-first; add sharing as feature
- Mark default views (admin)

Output:
1. Scope model
2. Sharing rules
3. Default-view selection
4. Per-user customization
5. Migration if changing model

The Linear personal-first pattern: each user gets own view; can opt-in to share. Lowers cognitive load; users don't worry about "did I just change everyone's view?"

2. Schema design

Design saved views schema.

Core table:

saved_views:
- id (UUID)
- workspace_id (multi-tenant)
- resource_type (enum: 'tasks', 'projects', 'customers')
- name (string)
- description (optional)
- filters (JSONB)
- sort (JSONB)
- group_by (string, optional)
- columns (JSONB - for tables)
- chart_config (JSONB - for charts)
- visualization_type (enum: 'table', 'kanban', 'calendar', 'list')
- owner_user_id
- visibility (enum: 'private', 'workspace', 'public')
- shared_with_user_ids (array, for granular)
- pinned (boolean)
- order (int, for sorting in nav)
- icon / emoji (optional)
- created_at, updated_at

Filter shape (JSONB):

{
  "operator": "AND",
  "conditions": [
    {"field": "status", "op": "in", "value": ["open", "in_progress"]},
    {"field": "assignee", "op": "eq", "value": "current_user"},
    {"field": "due_date", "op": "before", "value": "today + 7 days"}
  ]
}

Special values:
- "current_user" - dynamic (changes per viewer)
- "today" / "today + N days" - relative dates
- "@me" - shorthand for current user

Sort shape:
[{"field": "priority", "direction": "desc"}, {"field": "due_date", "direction": "asc"}]

Indexes:
- (workspace_id, resource_type, owner_user_id)
- (workspace_id, visibility) for shared views

Output:
1. Schema (DDL)
2. Filter JSONB structure
3. Special values for dynamic filters
4. Indexing
5. Multi-tenant scoping

The "current_user" dynamic: shared view "My open tickets" works for everyone. User who opens it sees their tickets, not creator's. Implemented via special placeholder.

3. Save view UI

Build save-view UI.

Flow:

1. User adjusts filters / sort / columns
2. Detect "current state differs from any saved view"
3. Show "Save view" button
4. Click → modal: name + visibility + icon
5. Save → view appears in nav

States:

Unsaved (filter changed):
- Filter bar shows "Modified"
- "Save" button highlighted

Saved (current state matches view):
- View name shown active
- "Save" button hidden / disabled

Modified saved view:
- View name + "Modified" indicator
- "Save changes" / "Save as new" / "Discard" options

Save dialog:
- Name (required)
- Description (optional)
- Icon / emoji (optional)
- Visibility:
  - Private (only me)
  - Workspace (everyone)
- Pin to sidebar (optional)

Update existing view:
- "Save changes" overwrites
- "Save as new" creates separate
- Permission check (can edit?)

Inline rename:
- Right-click view → rename
- Save without modal

Anti-patterns:
- "Save" auto-overwrites without ask
- No "save as new" option
- Modal too complex for simple saves

Output:
1. Save dialog
2. State indicators (unsaved / saved / modified)
3. Save flow (overwrite vs new)
4. Inline rename
5. Pinning to nav

The "Modified" indicator pattern: subtle "View name • Modified" tells users they've changed something. Clear "Save" / "Discard" actions.

4. View navigation — sidebar / tabs

How users see + access views.

Design view navigation.

Patterns:

Pattern A: Sidebar list (Linear / Notion)
- Dedicated sidebar section per resource type
- "My Views" + "Workspace Views" sections
- Star / pin to top
- Drag to reorder

Pattern B: Tabs above content
- Horizontal tabs at top of list
- Active view highlighted
- "+" to add new
- Used by: Notion databases

Pattern C: Dropdown
- Click view name → dropdown of all views
- More compact
- Used by: HubSpot

Pattern D: Hybrid
- Pinned views as tabs/sidebar
- All views in dropdown

Recommended for power-user products: sidebar (Linear-style); allows many views.

Sidebar UI:

Section structure:
- Default views (system; can't delete)
- My views (user-created)
- Team views (workspace-shared)

Each view item:
- Icon / emoji
- Name
- Count (optional - "12 open tickets")
- Active highlight
- Hover → context menu (rename, duplicate, delete, share)

Drag-and-drop reorder:
- Within section
- Persists to backend

Pinning:
- Star to pin to top
- Or: drag to "Pinned" subsection

Mobile:
- Sidebar hides; drawer / sheet
- Or: dropdown for narrow screens

Output:
1. Navigation pattern choice
2. Sidebar structure
3. View item design
4. Drag-reorder
5. Mobile fallback

The Linear sidebar pattern feels best for productivity tools: many views in compact list, easy to scan + select.

5. Filter UI — building queries

Saved views need a way to build them. Filter UI matters.

Build filter UI.

Approaches:

Faceted filters (recommended for most):
- Predefined facets: Status, Priority, Assignee, Tags
- Click facet → multi-select dropdown
- Pills above list show active filters
- Combinations: AND across facets, OR within

Operators per field:
- Text: contains, equals, starts with
- Date: is, before, after, between, in last X days
- Number: =, !=, <, >, between
- Single-select: is, is not
- Multi-select: contains, doesn't contain

Filter pills:

Display:
"Status: Open, In Progress" (multi-value)
"Assignee: @me" (special)
"Created: Last 7 days" (relative)

Click pill → reopen dropdown to edit
X icon → remove filter

"+ Add filter" button → field picker

Power-user query builder (advanced):
- Linear / Notion advanced filter
- AND / OR / nested groups
- For complex queries

Visualizations of filters:
- Compact pills above list
- Or: dedicated filter sidebar (Asana)

Empty state when filters return nothing:
- "No items match these filters"
- "Clear filters" button

URL state:
- Filters serialized to URL
- ?filters[status]=open,in_progress
- Shareable + bookmarkable

Output:
1. Faceted vs query-builder
2. Operators per field type
3. Pills design
4. URL state
5. Empty / no-match state

The "faceted by default + advanced when needed" pattern: 80% of users use faceted; 20% want SQL-like power. Don't force the simple users into the complex UI.

6. Sharing views — collaborative

Shared views require careful permission + edit handling.

Implement view sharing.

Visibility levels:

Private (default):
- Owner only
- Hidden from others

Workspace:
- All members can see + use
- Edit permission: owner only OR admin OR all

Specific users:
- Share with named members
- Granular control

Public link:
- Read-only URL share with non-members
- Risk: data exposure
- Requires explicit opt-in

Edit semantics:

Personal copy:
- User can edit local copy without affecting source
- "Save as new" creates personal version

Live sync:
- Edits to shared view affect everyone
- Owner / admin only can edit
- Confirmation on edit

Read-only:
- Use the view; can't modify

Recommendation:
- Workspace shared = read-only for non-owners
- Owner can edit; cascade to all viewers
- "Duplicate" for personal customization

Conflict scenarios:

Two users edit shared view at once:
- Last-writer-wins OR merge attempt
- Show warning: "This view has been updated"

Owner deletes shared view:
- Notify users who pinned it
- Option to "save as personal copy first"

User leaves workspace:
- Their personal views deleted (or transferred to admin)

Output:
1. Visibility levels
2. Edit semantics
3. Conflict handling
4. Owner-leaves rules
5. Audit log

The "personal copy" affordance: shared view becomes user's starting point; they "save as" to customize. Otherwise users feel locked out of personalization.

7. Default views per workspace / role

Workspace admins want to define defaults.

Default view configuration.

Patterns:

System defaults:
- "All" view (no filter)
- Recent / pinned
- Always available
- Can't be deleted

Workspace defaults:
- Admin sets "All open tickets" as default for everyone
- Users override per-session
- Used as starting point for new members

Role-based defaults:
- Different default for admins vs members
- Different for support vs engineering team

Per-resource defaults:
- Default view per database / table
- "Tasks" defaults to "My open"
- "Customers" defaults to "Active"

User override:
- User sets their own default
- Persists per workspace
- Falls back to workspace default if unset

Implementation:

User preferences:
- user_preferences table: default_view_id per resource_type per workspace

Workspace settings:
- workspace_settings: default_view_id per resource_type

Resolution:
- User pref > workspace default > system default

Onboarding:
- New user lands on workspace default (or system)
- Tour highlights views feature

Output:
1. Default-view hierarchy
2. User preference storage
3. Workspace admin UI
4. Role-based variants
5. Onboarding integration

The "smart default" rule: don't show "All" as default. Show "My open / In progress" for tasks; "Active customers" for customers. Filtered defaults match user intent better.

8. Performance — many views, large datasets

Saved views can multiply queries. Plan performance.

Optimize view performance.

Query patterns:

View count:
- "Show count next to view name (e.g., '12 open tickets')"
- Each view = COUNT query
- 10 views in sidebar = 10 COUNTs
- Combine into single query (subquery per view)
- Or: cache counts; refresh on data change

View load:
- Server-side filter + sort + paginate
- Don't load all data + filter client-side
- Index commonly-filtered fields

Real-time updates:
- WebSocket / SSE: when data changes, update relevant view counts
- Don't refetch all views; just invalidate affected

Stale data:
- Show last-updated timestamp on view
- Refresh button if user wants fresh

Pagination:
- 50-100 items per page typical
- Cursor pagination for large datasets
- See data-tables-sort-filter-bulk

Query plan:
- EXPLAIN ANALYZE common view queries
- Add indexes if seq-scanning
- Avoid: WHERE on computed columns without indexes

Caching:
- Per-view cache (Redis / in-memory)
- TTL: 30s for active views; longer for stale
- Invalidate on relevant data change

Anti-patterns:
- Loading all data + client-filtering (slow at 1000+ items)
- COUNT(*) on every view in sidebar (N+1)
- No indexing on filtered fields

Output:
1. Server-side filtering pattern
2. Index strategy per view
3. Count optimization
4. Caching strategy
5. Real-time invalidation

The N+1 view-count trap: 10 views in sidebar = 10 SELECT COUNT queries on every page load. Combine into single CTE / subquery; massive perf gain.

9. View as URL — shareable + deep-linkable

URLs make views shareable.

URL state for views.

Pattern:

/[workspace]/tasks/views/[view_id]
Or
/[workspace]/tasks?view=view_id
Or
/[workspace]/tasks?filters[status]=open&sort=priority

Tradeoffs:

By view ID (clean):
- Shorter URL
- View must exist + be accessible
- Renaming view doesn't break URL

By filter params (transparent):
- URL shows filters explicitly
- Shareable even if recipient doesn't have view saved
- Longer URLs

Hybrid (recommended):
- Saved views: by ID
- Ad-hoc filters: by params
- Switch URL when user saves

Sharing flow:

User clicks share:
- Get URL
- Copy to clipboard
- Send

Recipient clicks:
- If view exists + recipient has access → load
- If not (different workspace, deleted, no permission) → fallback to "All" + show error

Embedded views:
- Embed view in email / external doc
- Static snapshot at time of embed
- Or: live link (recipient must auth)

Mobile:
- Same URL pattern works
- Native app deep-link if available

Output:
1. URL pattern decision
2. View ID vs params
3. Share flow
4. Fallback handling
5. Mobile / embed support

The pattern most-loved by users: URL preserves whatever you're looking at. Reload doesn't lose state; bookmark works; share works.

10. Templates — pre-built views

Provide templates so users don't start from scratch.

Pre-built view templates.

System templates per resource type:

Tasks:
- "All tasks"
- "My open tasks"
- "Due this week"
- "Completed last 7 days"
- "Blocked"

Projects:
- "All projects"
- "Active projects"
- "Projects I own"

Customers:
- "All customers"
- "Active customers"
- "Recently signed up"
- "At risk"

Each template:
- Pre-set filters
- Pre-set sort
- Default visualization
- Editable copy if user wants to customize

Onboarding:
- Show templates during first-time
- "Add template view to your sidebar"
- Lower friction than building from scratch

User-shareable templates:
- Power user creates view → shares as workspace template
- Other users adopt as starting point

AI suggestions (advanced):
- LLM analyzes user's data patterns
- Suggests views: "You filter by 'urgent' often. Save as view?"
- Used by: Notion AI

Output:
1. System template library per resource
2. Template UI in onboarding
3. User-shared templates
4. AI suggestions (optional)
5. Template management

The "default view library" reduces blank-page problem. New user opens app, sees pre-built useful views, immediately productive.

What Done Looks Like

A v1 saved-views system for B2B SaaS in 2026:

  • Schema with views table + filter / sort JSONB
  • Personal + workspace-shared views
  • Save / update / delete view UI
  • Sidebar / tab navigation
  • Faceted filter UI with pills
  • URL state per view
  • Defaults per user + workspace
  • Multi-tenant isolation
  • Performance (indexed; cached counts)
  • Mobile-friendly UX
  • System templates for new users

Add later when product is mature:

  • Advanced query builder (AND / OR / nested)
  • AI-suggested views
  • View templates from community
  • Pinning to sidebar
  • Per-view notifications ("alert when count changes")
  • View analytics (most-used views)

The mistake to avoid: view-state on every page load = COUNT explosion. Combine; cache.

The second mistake: shared views with no edit clarity. Confusing whose changes affect whom. Personal-first model is safer.

The third mistake: no URL state. Sharing / bookmarking broken.

See Also