Skip to main content

Overview

CricTalk is packed with features designed specifically for cricket enthusiasts. From sharing your match analysis to competing on the leaderboard, every feature is crafted to enhance your cricket discussions.

Social posts

Share thoughts, images, and engage with the community

Live match rooms

Real-time chat rooms for live cricket matches

Leaderboard

Compete based on your engagement and activity

Notifications

Stay updated with push notifications

Authentication

Secure user authentication with Appwrite

User profiles

Personalized profiles with stats and preferences

Social posts

Share your cricket opinions, analysis, and moments with the community through rich social posts.

Post creation

Create posts with text content up to 512 characters, with optional image attachments:
schemas/PostSchema.ts
export const PostSchema = z.object({
  content: z
    .string()
    .min(1, "Post can not be empty.")
    .max(512, "Post can not be more than 512 characters"),
  image: z.array(z.string()).optional(),
});

Engagement tracking

Every post automatically tracks multiple engagement metrics:
schemas/PostSchema.ts
export interface Post extends Models.Row {
  content: string;
  image?: string[];
  
  authorId: string;
  authorName: string;
  
  likes: number;
  likedBy: string[];  // Prevents duplicate likes
  
  views: number;
  viewedBy: string[];  // Tracks unique views
  
  commentCount: number;
}
Views are automatically incremented when a post is 60% visible in the feed, ensuring accurate view tracking.

Like functionality

Users can like posts with a single tap. The system prevents duplicate likes by tracking user IDs:
services/posts.service.ts
export async function executePost({
  action,
  postId,
  content,
  images,
}: {
  action: "create" | "update" | "delete" | "like" | "view";
  content?: string;
  postId?: string;
  images?: string[];
}) {
  const execution = await functions.createExecution({
    functionId: POSTS_GUARD_FUNCTION_ID,
    body: JSON.stringify({ action, content, postId, images }),
    async: false,
  });
  
  if (execution.status === "failed") {
    throw new Error(`Post execution failed ${execution.errors}`);
  }
  
  return execution;
}

Comments

Engage in detailed discussions with nested comments on any post. Comments support:
  • Create, edit, and delete operations
  • Author attribution
  • Timestamp tracking
  • Comment count updates on parent posts

Search functionality

Find posts quickly with full-text search:
services/posts.service.ts
export async function searchPosts(query: string) {
  if (!query.trim()) return fetchPosts();
  
  return await tablesDB.listRows<Post>({
    databaseId: CRIC_TALK_DATABASE_ID,
    tableId: POSTS_TABLES_ID,
    queries: [
      Query.search("content", query),
      Query.orderDesc("views"),
      Query.orderDesc("likes"),
      Query.orderDesc("$createdAt"),
    ],
  });
}
Search results are ranked by views, likes, and recency to surface the most relevant content.

Live match chat rooms

Join dedicated chat rooms for live cricket matches and discuss the action in real-time.

Room creation

Create rooms for upcoming matches with comprehensive match details:
schemas/RoomSchema.ts
export const RoomSchema = z.object({
  teams: z.array(
    z
      .string()
      .min(3, "Team name must be at least 3 characters.")
      .max(8, "Team name can not be more than 8 characters"),
  ),
  
  startTime: z.string().min(1, "Invalid room start time."),
  endTime: z.string().min(1, "Invalid room end time.").optional(),
  
  matchType: z
    .enum(["ODI", "TEST", "T20"], "Match type must be ODI, TEST or T20.")
    .transform((t) => t.toLowerCase()),
  
  isLocked: z.boolean("Invalid chat lock option."),
});

Smart status tracking

Rooms automatically update their status based on match timings:
  • Upcoming - Match hasn’t started yet (blue indicator)
  • Live - Match is currently in progress (orange indicator)
  • Finished - Match has concluded (gray indicator)
services/rooms.service.ts
const updatedRooms: Room[] = rooms.map((item: Room) => {
  let status: "upcoming" | "live" | "finished";
  const now = Date.now();
  const start = new Date(item.startTime).getTime();
  const end = new Date(item.endTime || "").getTime();
  
  if (end < now) {
    status = "finished";
  } else if (start > now) {
    status = "upcoming";
  } else {
    status = "live";
  }
  
  return { ...item, status };
});

Real-time messaging

Send and receive messages instantly within match rooms. Messages are handled through Appwrite serverless functions for optimal performance and security.

Room management

Room creators can:
  • Edit room details (teams, timings, match type)
  • Lock/unlock chat to prevent spam
  • Delete rooms when needed
Only the room creator (authorId) can edit or delete a room. This ensures proper content moderation.

Leaderboard system

Compete with other cricket fans based on your engagement and activity.

Ranking criteria

The leaderboard ranks users by their message count in chat rooms:
interfaces/UserStats.ts
export interface UserStats extends Models.Row {
  username: string;
  messageCount: number;
}

Top performers

The leaderboard highlights the top 10 users:
  • Top 3 users are displayed on a podium with special styling
  • Ranks 4-10 are shown in a scrollable list
app/(tabs)/LeaderboardScreen.tsx
// Fetch leaderboard data
const data = await functions.createExecution({
  functionId: process.env.EXPO_PUBLIC_APPWRITE_LEADERBOARD_GUARD_FUNCTION_ID!,
  async: false,
});
const leaderboardData = JSON.parse(data.responseBody).rows;

setUserStatsLeaderboard(leaderboardData);
Increase your message count by actively participating in match room discussions to climb the leaderboard!

Push notifications

Stay connected with real-time push notifications for important events.

Notification types

Receive notifications for:
  • New likes on your posts
  • Comments on your posts
  • Replies to your comments
  • Match room updates
  • Important announcements

Notification management

View all your notifications in a dedicated screen with:
  • Timestamp for each notification
  • Read/unread status
  • Quick actions to view related content
services/notifications.service.ts
export async function executeNotification({
  action,
}: {
  action: "fetchByUserId";
}) {
  const execution = await functions.createExecution({
    functionId: NOTIFICATIONS_GUARD_FUNCTION_ID,
    body: JSON.stringify({ action }),
    async: false,
  });
  
  if (execution.status === "failed") {
    throw new Error("Notification execution failed");
  }
  
  return execution;
}

Push token registration

CricTalk automatically registers your device for push notifications using Expo Notifications, ensuring you never miss important updates.

User authentication

Secure authentication powered by Appwrite ensures your account is protected.

Email and password authentication

Create an account or log in with email and password:
services/auth.service.ts
export async function createUserWithEmailAndPassword(
  email: string,
  password: string,
) {
  await account.create({
    userId: ID.unique(),
    email,
    password,
  });
}

export async function loginUserWithEmailAndPassword(
  email: string,
  password: string,
) {
  await account.createEmailPasswordSession({ email, password });
}

Session management

Appwrite automatically handles session management, keeping you logged in securely:
libs/appwrite.ts
const API_ENDPOINT = process.env.EXPO_PUBLIC_APPWRITE_API_ENDPOINT!;
const PROJECT_ID = process.env.EXPO_PUBLIC_APPWRITE_PROJECT_ID!;

export const client = new Client()
  .setEndpoint(API_ENDPOINT)
  .setProject(PROJECT_ID);

export const account = new Account(client);

Protected routes

The app automatically redirects unauthenticated users to the login screen, ensuring all features are protected.

User profiles

Personalize your CricTalk experience with customizable user profiles.

Profile information

Your profile displays:
  • Username (shown as avatar initial throughout the app)
  • Message count and leaderboard rank
  • Posts you’ve created
  • Rooms you’ve joined

Settings and preferences

Customize your experience through:
  • Account settings - Update profile information
  • Login & Security - Manage authentication settings
  • Preferences - Customize app behavior

Your activity

View all your posts and engagement in one place by filtering posts by your user ID:
services/posts.service.ts
export async function fetchPostsByUserId(userId: string) {
  return await tablesDB.listRows<Post>({
    databaseId: CRIC_TALK_DATABASE_ID,
    tableId: POSTS_TABLES_ID,
    queries: [Query.equal("authorId", userId), Query.orderDesc("$createdAt")],
  });
}

State management with Zustand

CricTalk uses Zustand for lightweight, efficient state management across the app:
  • usePosts - Manages post state (add, update, delete, setPosts)
  • useRooms - Manages room state and chat messages
  • useComments - Manages comment state
  • useUser - Manages user profile and authentication state
This ensures optimal performance and real-time updates across all screens.
All state stores are persisted using AsyncStorage, providing a seamless experience even when offline.

Build docs developers (and LLMs) love