◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Getting Started
◈ Getting Started/2026-03-23Beginner

How to Build a Note-Taking App with Rork — A Complete Beginner's Tutorial

Learn how to build a fully functional note-taking app with Rork from scratch. This step-by-step tutorial covers data persistence with AsyncStorage, real-time search, and category filtering.

Rork585note-taking appmemo apptutorial20AsyncStorage10React Native239beginner21

Why a Notes App Makes a Good First Build

Note-taking apps are among the most universally used mobile applications. From Apple Notes to Google Keep, millions of people rely on them daily to capture ideas, organize tasks, and stay productive.

The structure is simple, yet it packs in the fundamentals — saving, listing, searching. That combination makes a notes app an unusually good first project in Rork. Starting from an empty project, you'll end up with persistence through AsyncStorage and working search in a single app.

What you'll learn:

  • How to design the screen structure for a notes app in Rork
  • Data persistence using AsyncStorage (save and load notes locally)
  • Real-time search across note titles and content
  • Category tagging and filtering
  • Tips for achieving a professional-quality design

Who this is for: Anyone getting started with Rork, or anyone who wants to learn by building a practical, everyday app.

Prerequisites and Setup

What You'll Need

Before diving in, make sure you have:

  • A Rork account: Sign up for free at rork.com (the Free plan allows up to 5 project generations per week)
  • A modern browser: Chrome or Safari, latest version
  • A smartphone: For live preview on a real device (iOS or Android)

Rork Basics

If this is your first time using Rork, start with the Getting Started guide to familiarize yourself with project creation and the preview workflow.

Step 1 — Creating Your Project with the Right Prompt

The most critical part of building an app with Rork is crafting your initial prompt. A well-structured prompt helps the AI generate a polished app on the first try.

Recommended Prompt

Enter the following in Rork's project creation screen:

Build a note-taking app with the following specifications:
 
[Screens]
1. Notes List (Home): Display note titles with timestamps in a scrollable list
2. Note Editor: A form with title and body text fields
3. Search: Keyword search across all notes
 
[Features]
- Create, edit, and delete notes (swipe-to-delete support)
- Local persistence using AsyncStorage
- Real-time search across titles and content
- Category tags: Work, Personal, Ideas, Shopping
- Category-based filtering
- Automatic timestamps with sort-by-date
 
[Design]
- Clean, minimal UI
- Light and dark mode support
- Color-coded category badges

The key here is separating your instructions into screens, features, and design. Rork's AI uses this structure to generate appropriate components, navigation, and styling automatically.

Step 2 — Data Model and Storage Design

At the heart of any notes app is its data model. Here's what Rork generates for the note structure:

// types/Note.ts — Note data type definition
export interface Note {
  id: string;          // Unique ID (UUID)
  title: string;       // Note title
  content: string;     // Note body
  category: Category;  // Category tag
  createdAt: string;   // Created timestamp (ISO 8601)
  updatedAt: string;   // Last updated timestamp
}
 
// Category definitions
export type Category = 'work' | 'personal' | 'idea' | 'shopping';
 
// Display labels and colors for each category
export const CATEGORIES: Record<Category, { label: string; color: string }> = {
  work: { label: 'Work', color: '#4A90D9' },
  personal: { label: 'Personal', color: '#7ED321' },
  idea: { label: 'Ideas', color: '#F5A623' },
  shopping: { label: 'Shopping', color: '#D0021B' },
};

Persisting Data with AsyncStorage

AsyncStorage ensures your notes survive app restarts. Here's the storage utility Rork generates:

// utils/storage.ts — Save, load, and delete notes
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Note } from '../types/Note';
 
const STORAGE_KEY = '@notes_app_data';
 
// Load all notes
export const loadNotes = async (): Promise<Note[]> => {
  try {
    const json = await AsyncStorage.getItem(STORAGE_KEY);
    return json ? JSON.parse(json) : [];
  } catch (error) {
    console.error('Failed to load notes:', error);
    return [];
  }
};
 
// Save notes (overwrites entire array)
export const saveNotes = async (notes: Note[]): Promise<void> => {
  try {
    await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(notes));
  } catch (error) {
    console.error('Failed to save notes:', error);
  }
};
 
// Expected behavior:
// - loadNotes() → Returns saved notes array (empty array on first run)
// - saveNotes([...]) → Persists the notes array to device storage

AsyncStorage is a key-value store that saves data as JSON strings. It works well for personal note-taking apps. For apps handling tens of thousands of records, consider migrating to SQLite, but AsyncStorage is more than sufficient for most use cases.

For a deeper dive into offline data strategies, check out Building Offline-Ready Apps with AsyncStorage and NetInfo.

Step 3 — Building the Notes List Screen

The notes list is the first screen users see, so readability and ease of interaction are paramount.

// screens/NoteListScreen.tsx — Core notes list implementation
import React, { useState, useEffect, useCallback } from 'react';
import { FlatList, View, Text, TouchableOpacity, Alert } from 'react-native';
import { loadNotes, saveNotes } from '../utils/storage';
import { Note, CATEGORIES } from '../types/Note';
 
export default function NoteListScreen({ navigation }) {
  const [notes, setNotes] = useState<Note[]>([]);
  const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
 
  // Load notes whenever the screen comes into focus
  useEffect(() => {
    const unsubscribe = navigation.addListener('focus', async () => {
      const saved = await loadNotes();
      // Sort by most recently updated
      setNotes(saved.sort((a, b) =>
        new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
      ));
    });
    return unsubscribe;
  }, [navigation]);
 
  // Delete a note with confirmation
  const deleteNote = useCallback(async (id: string) => {
    Alert.alert('Delete Note', 'Are you sure you want to delete this note?', [
      { text: 'Cancel', style: 'cancel' },
      {
        text: 'Delete',
        style: 'destructive',
        onPress: async () => {
          const updated = notes.filter(n => n.id !== id);
          setNotes(updated);
          await saveNotes(updated);
        },
      },
    ]);
  }, [notes]);
 
  // Apply category filter
  const filteredNotes = selectedCategory
    ? notes.filter(n => n.category === selectedCategory)
    : notes;
 
  return (
    <View style={{ flex: 1, padding: 16 }}>
      {/* Category filter buttons */}
      <CategoryFilter
        selected={selectedCategory}
        onSelect={setSelectedCategory}
      />
      {/* Notes list */}
      <FlatList
        data={filteredNotes}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <NoteCard
            note={item}
            onPress={() => navigation.navigate('Edit', { noteId: item.id })}
            onDelete={() => deleteNote(item.id)}
          />
        )}
        ListEmptyComponent={
          <Text style={{ textAlign: 'center', marginTop: 40, color: '#999' }}>
            No notes yet. Tap the + button to create one!
          </Text>
        }
      />
    </View>
  );
}

Why FlatList Matters

React Native's FlatList only renders items currently visible on screen. This means your app stays smooth and responsive even if you have hundreds or thousands of notes — it won't try to render them all at once.

Step 4 — Adding Real-Time Search

As your note collection grows, search becomes essential. Here's how to implement keyword-based filtering:

// hooks/useNoteSearch.ts — Custom hook for note search
import { useMemo } from 'react';
import { Note } from '../types/Note';
 
export function useNoteSearch(notes: Note[], query: string): Note[] {
  return useMemo(() => {
    if (!query.trim()) return notes;
 
    const lowerQuery = query.toLowerCase();
    return notes.filter(note =>
      note.title.toLowerCase().includes(lowerQuery) ||
      note.content.toLowerCase().includes(lowerQuery)
    );
  }, [notes, query]);
 
  // Expected behavior:
  // useNoteSearch(allNotes, '') → Returns all notes
  // useNoteSearch(allNotes, 'meeting') → Returns only notes containing "meeting"
}

The useMemo hook ensures filtering only runs when the notes array or search query actually changes, keeping the UI responsive during rapid typing.

Adding Search via Rork Chat

If you didn't include search in your initial prompt, you can easily add it through Rork's chat interface:

Add a search bar at the top of the notes list screen.
It should search across both titles and content in real time.
Show a "X results found" label below the search bar while filtering.

Step 5 — Polishing the Design

A few small design touches can transform your note-taking app from functional to professional.

Color-Coded Category Badges

Adding visual category badges to each note card dramatically improves scannability:

// components/CategoryBadge.tsx — Category badge component
import React from 'react';
import { View, Text } from 'react-native';
import { Category, CATEGORIES } from '../types/Note';
 
export function CategoryBadge({ category }: { category: Category }) {
  const { label, color } = CATEGORIES[category];
  return (
    <View style={{
      backgroundColor: color + '20', // 20% opacity background
      paddingHorizontal: 8,
      paddingVertical: 3,
      borderRadius: 12,
      alignSelf: 'flex-start',
    }}>
      <Text style={{ color, fontSize: 12, fontWeight: '600' }}>
        {label}
      </Text>
    </View>
  );
}

Dark Mode Support

When you include "dark mode" in your Rork prompt, the AI generates automatic theme switching using React Native's useColorScheme hook. For further customization, use the chat to specify exact colors — for example, "Set the dark mode background to #1A1A2E" — and Rork will update the theme accordingly.

Wrapping Up — Start Your App Journey with a Notes App

A note-taking app is the perfect first project. It's simple enough for beginners yet covers fundamental patterns that appear in almost every mobile app:

  1. Data modeling — Defining type-safe structures with TypeScript
  2. Data persistence — Keeping data alive between sessions with AsyncStorage
  3. Efficient list rendering — Using FlatList for smooth scrolling at scale
  4. Real-time search — Optimized filtering with useMemo
  5. Category management — Organized, filterable content with visual cues

From here, you could extend the app with Markdown support, reminders, cloud sync, or rich text editing — all features that could make your app ready for the App Store. Fire up Rork, paste in the prompt, and start building your own notes app today.

As a next step, try Build Your First Rork App in 30 Minutes to get more comfortable with the workflow, or How to Build a To-Do App to learn task management patterns.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

◈ Getting Started2026-09-14
Rork No Longer Creates New Expo Projects: Keep Yours, or Rebuild It in SwiftUI?
You can no longer start an Expo project in Rork, but existing ones keep building and shipping. Here is how to decide whether to stay on Expo or rebuild in SwiftUI, and what quietly goes missing when you rebuild.
◈ Getting Started2026-09-08
Whether You Need Rork Max Is Answered by Your Permissions, Not the Price Page
When I cannot decide between standard Rork and Rork Max, I stop reading the price page. Instead I pull every OS capability my app actually asks for out of app.json and Info.plist, then sort them into what Expo covers, what a config plugin covers, and what truly needs native Swift.
◈ Getting Started2026-08-17
Write .gitignore Before You Run git init on an Exported Rork Project
Running git init on a freshly exported Rork project puts your signing keys and .env straight into history. I measured what gets committed when the ignore file comes first versus last, and which exclusion patterns actually work.