Thanks to visit codestin.com
Credit goes to github.com

Skip to content

heyjunin/v1-neon

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

hero

V1 Neon - Enhanced Boilerplate

An enhanced open-source starter kit based on Midday with modern database architecture.

Original Website Β· Issues Β· What's included Β· Prerequisites Β· Getting Started Β· Architecture Β· Features

This is an enhanced version of the V1 boilerplate with significant improvements including database decoupling from Supabase, Neon PostgreSQL integration, advanced seeder system, multi-tenancy support, and modern development practices.

πŸš€ What's New

πŸ”„ Database Architecture Overhaul

  • Decoupled from Supabase: Database operations now use Neon PostgreSQL with Drizzle ORM
  • Supabase Auth Only: Supabase is now used exclusively for authentication
  • Type-safe Database: Full TypeScript support with Drizzle ORM
  • Migration System: Robust migration management with Drizzle Kit

πŸ”— API Architecture (BFF Pattern)

  • tRPC as BFF: Type-safe API layer implemented as Backend for Frontend within the app
  • End-to-end Type Safety: Shared types between client and server
  • Integrated Authentication: Seamless auth integration with Supabase
  • Optimized for Frontend: API designed specifically for frontend needs

🌱 Advanced Seeder System

  • Laravel-inspired Seeders: Powerful seeder system with faker.js integration
  • Batch Operations: Efficient data insertion with transaction support
  • Realistic Data: Generate realistic fake data with consistent seeds
  • Force Mode: Override protection with --force flag

🏒 Multi-tenancy Support

  • Organizations Module: Complete multi-tenancy system
  • Team Management: Role-based access control (owner, admin, member)
  • Invite System: Secure email-based invitation system
  • Permission System: Granular permissions per organization

πŸ”§ Development Experience

  • Bun Package Manager: Faster package management and scripts
  • Enhanced Scripts: Automated setup and provisioning
  • Better Error Handling: Comprehensive error tracking and logging
  • Type Safety: End-to-end TypeScript support

πŸ“ Storage System

  • Cloudflare R2: S3-compatible object storage
  • Image Transformations: Real-time image processing with Sharp
  • Presigned URLs: Secure upload/download URLs
  • File Validation: Type and size validation
  • React Components: Ready-to-use upload components

What's included

Next.js - Framework
Turborepo - Build system
Biome - Linter, formatter
TailwindCSS - Styling
Shadcn - UI components
TypeScript - Type safety
Neon PostgreSQL - Primary Database
Drizzle ORM - Type-safe ORM
Supabase - Authentication Only
Upstash - Cache and rate limiting
React Email - Email templates
Resend - Email delivery
i18n - Internationalization
Sentry - Error handling/monitoring
Dub - Sharable links
Trigger.dev - Background jobs
OpenPanel - Analytics
Polar - Billing (coming soon)
react-safe-action - Validated Server Actions
nuqs - Type-safe search params state manager
next-themes - Theme manager
tRPC - Type-safe BFF API
Cloudflare R2 - Object Storage
Sharp - Image Processing

πŸ—οΈ Architecture

Database Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Supabase      β”‚    β”‚   Neon          β”‚    β”‚   Drizzle ORM   β”‚
β”‚   (Auth Only)   β”‚    β”‚   PostgreSQL    β”‚    β”‚   (Type-safe)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                       β”‚                       β”‚
         β”‚                       β”‚                       β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Application   β”‚
                    β”‚   (Next.js)     β”‚
                    β”‚   + tRPC BFF    β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Directory Structure

.
β”œβ”€β”€ apps                         # App workspace
β”‚    β”œβ”€β”€ api                     # Supabase (Auth, Storage, Edge Functions)
β”‚    β”œβ”€β”€ app                     # Main application (with tRPC BFF)
β”‚    β”œβ”€β”€ web                     # Marketing site
β”‚    └── email                   # Email templates
β”œβ”€β”€ packages                     # Shared packages
β”‚    β”œβ”€β”€ analytics               # OpenPanel analytics
β”‚    β”œβ”€β”€ database                # πŸ†• Neon + Drizzle ORM
β”‚    β”‚   β”œβ”€β”€ src/
β”‚    β”‚   β”‚   β”œβ”€β”€ schema/         # Database schemas
β”‚    β”‚   β”‚   β”œβ”€β”€ queries/        # Database queries
β”‚    β”‚   β”‚   β”œβ”€β”€ mutations/      # Database mutations
β”‚    β”‚   β”‚   β”œβ”€β”€ seeders/        # πŸ†• Seeder system
β”‚    β”‚   β”‚   └── adapters/       # Database adapters
β”‚    β”‚   └── migrations/         # Drizzle migrations
β”‚    β”œβ”€β”€ email                   # React email library
β”‚    β”œβ”€β”€ jobs                    # Trigger.dev background jobs
β”‚    β”œβ”€β”€ kv                      # Upstash rate-limited storage
β”‚    β”œβ”€β”€ logger                  # Logger library
β”‚    β”œβ”€β”€ supabase                # Supabase (Auth only)
β”‚    β”œβ”€β”€ storage                 # πŸ†• Cloudflare R2 storage
β”‚    β”‚   β”œβ”€β”€ src/
β”‚    β”‚   β”‚   β”œβ”€β”€ client.ts       # Client-side storage
β”‚    β”‚   β”‚   β”œβ”€β”€ server.ts       # Server-side R2 storage
β”‚    β”‚   β”‚   β”œβ”€β”€ components/     # React upload components
β”‚    β”‚   β”‚   └── utils.ts        # Storage utilities
β”‚    β”‚   └── types.ts            # Storage types
β”‚    └── ui                      # Shared UI components
β”œβ”€β”€ scripts                      # πŸ†• Setup and automation scripts
β”‚    β”œβ”€β”€ setup-neon.js          # Neon database setup
β”‚    β”œβ”€β”€ setup-env.js           # Environment setup
β”‚    β”œβ”€β”€ setup-storage.js       # Storage setup
β”‚    └── supabase-*.sh          # Supabase management
β”œβ”€β”€ tooling                      # Shared configurations
└── docs/                        # πŸ†• Documentation

🎯 Features

πŸ—„οΈ Database Features

  • Neon PostgreSQL: Serverless PostgreSQL with automatic scaling
  • Drizzle ORM: Type-safe database operations
  • Migration Management: Version-controlled schema changes
  • Seeder System: Laravel-inspired data seeding with faker.js
  • Transaction Support: ACID-compliant operations
  • Performance Optimization: Indexed queries and batch operations

🏒 Multi-tenancy Features

  • Organizations: Complete multi-tenant architecture
  • Team Management: Role-based access control
  • Invite System: Email-based invitations with tokens
  • Permission System: Granular permissions per organization
  • Isolation: Data isolation between tenants

πŸ” Authentication Features

  • Supabase Auth: OAuth providers (Google, Discord, GitHub)
  • Email/Password: Traditional email and password authentication
  • Magic Link: Passwordless authentication via email links
  • Password Reset: Secure password recovery system
  • Session Management: Secure session handling
  • Role-based Access: Integration with organization roles
  • Email Verification: Secure email verification flow

πŸš€ Development Features

  • Type Safety: End-to-end TypeScript support
  • tRPC BFF: Type-safe API layer implemented as Backend for Frontend
  • Hot Reload: Fast development experience
  • Error Tracking: Comprehensive error monitoring
  • Performance Monitoring: Real-time performance insights

πŸ“ Storage Features

  • Cloudflare R2: S3-compatible object storage
  • Image Transformations: Real-time image processing with Sharp
  • Presigned URLs: Secure upload/download URLs
  • File Validation: Type and size validation
  • React Components: Ready-to-use upload components
  • Batch Operations: Multiple file uploads
  • Progress Tracking: Real-time upload progress

Prerequisites

Getting Started

1. Clone the Repository

git clone <your-repo-url>
cd v1-neon

2. Install Dependencies

bun install

3. Setup Environment

# Copy environment files
cp apps/app/env.local.example apps/app/.env.local
cp apps/api/.env.example apps/api/.env

# Setup complete environment
bun run setup:env:complete

4. Setup Database

# Setup Neon database (automated)
bun run setup:neon

# Or manually setup database
bun run db:setup

5. Setup Storage

# Setup Cloudflare R2 storage
bun run setup:storage

6. Start Development

# Start all services
bun dev

# Or start specific services
bun dev:app    # Main application
bun dev:web    # Marketing site
bun dev:api    # API services
bun dev:email  # Email templates

πŸ—„οΈ Database Management

Commands

# Generate migration
bun run db:generate

# Run migrations
bun run db:migrate

# Push schema changes
bun run db:push

# Open Drizzle Studio
bun run db:studio

# Setup database (migrate + seed)
bun run db:setup

# Reset database
bun run db:reset

Seeder System

# Run all seeders
bun run seed:run

# Run specific seeders
bun run seed:run users,posts

# List available seeders
bun run seed:list

# Force run (overwrite existing data)
bun run seed:run --force

# Show help
bun run seed:help

Available Seeders

  • database: Runs all seeders in correct order
  • users: Creates sample users with realistic data
  • posts: Creates sample posts distributed among users
  • organizations: Creates sample organizations with members
  • example-advanced: Demonstrates advanced faker features

πŸ”— tRPC BFF API

The tRPC API is implemented as a Backend for Frontend (BFF) pattern within the main application:

Features

  • Type-safe API: End-to-end TypeScript support between client and server
  • Integrated Authentication: Seamless auth integration with Supabase
  • Optimized for Frontend: API designed specifically for frontend needs
  • Automatic Caching: React Query integration for optimal performance
  • Error Handling: Comprehensive error handling with type safety

Authentication Routes

  • auth.signUp - Email/password registration
  • auth.signIn - Email/password login
  • auth.signOut - User logout
  • auth.resetPassword - Password reset request
  • auth.updatePassword - Password update after reset
  • auth.sendMagicLink - Passwordless authentication
  • auth.sendOtp - Send OTP code
  • auth.verifyOtp - Verify OTP code
  • auth.updateProfile - Update user profile
  • auth.changePassword - Change user password
  • auth.deleteAccount - Delete user account
  • auth.getCurrentUser - Get current user data
  • auth.isAuthenticated - Check authentication status

Usage

Authentication Example

import { useSignIn, useSignUp, useSendMagicLink } from '@/lib/trpc';

function AuthExample() {
  const signIn = useSignIn();
  const signUp = useSignUp();
  const sendMagicLink = useSendMagicLink();

  const handleSignIn = async (email: string, password: string) => {
    try {
      await signIn.mutateAsync({ email, password });
      // Redirect to dashboard
    } catch (error) {
      console.error('Sign in failed:', error);
    }
  };

  const handleSignUp = async (email: string, password: string, fullName: string) => {
    try {
      await signUp.mutateAsync({ email, password, fullName });
      // Show email confirmation message
    } catch (error) {
      console.error('Sign up failed:', error);
    }
  };

  const handleMagicLink = async (email: string) => {
    try {
      await sendMagicLink.mutateAsync({ email });
      // Show magic link sent message
    } catch (error) {
      console.error('Magic link failed:', error);
    }
  };
}

Posts Example

import { usePosts, useCreatePost } from '@/lib/trpc';

function PostsPage() {
  const { data: posts, isLoading } = usePosts({
    search: 'react',
    page: 1,
    limit: 10
  });
  
  const createPost = useCreatePost();

  const handleCreate = async (data) => {
    try {
      await createPost.mutateAsync(data);
    } catch (error) {
      if (error.data?.code === 'UNAUTHORIZED') {
        console.log('User needs to login');
      }
    }
  };

  return (
    <div>
      {posts?.data.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  );
}

API Structure

apps/app/src/lib/trpc/
β”œβ”€β”€ client.ts          # tRPC client configuration
β”œβ”€β”€ provider.tsx       # React Query provider
β”œβ”€β”€ hooks.ts           # Custom hooks for API calls
β”œβ”€β”€ types.ts           # Shared types
β”œβ”€β”€ context.ts         # Server context (auth, etc.)
β”œβ”€β”€ server.ts          # Server exports (routers)
└── routers/
    β”œβ”€β”€ posts.ts       # Posts API routes
    └── organizations.ts # Organizations API routes

πŸ“ Storage System

The Storage system provides comprehensive file management with Cloudflare R2:

Features

  • Direct Upload: Upload files directly to Cloudflare R2
  • Image Transformations: Real-time image processing with Sharp
  • Presigned URLs: Secure upload/download URLs
  • File Validation: Type and size validation
  • React Components: Ready-to-use upload components
  • Batch Operations: Multiple file uploads
  • Progress Tracking: Real-time upload progress

Usage

import { FileUpload } from '@v1/storage/components';
import { createClientStorage } from '@v1/storage/client';

function UploadComponent() {
  const clientStorage = createClientStorage({
    uploadUrl: '/api/upload',
    maxFileSize: 10 * 1024 * 1024, // 10MB
    allowedTypes: ['image/*', 'application/pdf']
  });

  const handleUpload = async (file: File) => {
    const formData = new FormData();
    formData.append('file', file);
    
    const response = await fetch('/api/upload', {
      method: 'POST',
      body: formData
    });
    
    return response.json();
  };

  return (
    <FileUpload
      onUpload={handleUpload}
      accept="image/*"
      maxSize={5 * 1024 * 1024} // 5MB
      multiple={true}
      onUploadComplete={(result) => {
        console.log('Upload completed:', result);
      }}
    />
  );
}

Server-Side Usage

import { createR2Storage } from '@v1/storage/server';

const storage = createR2Storage({
  accountId: process.env.R2_ACCOUNT_ID!,
  accessKeyId: process.env.R2_ACCESS_KEY_ID!,
  secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
  bucketName: process.env.R2_BUCKET_NAME!,
});

// Upload file
const result = await storage.upload('uploads/image.jpg', fileBuffer, {
  contentType: 'image/jpeg',
  public: true,
  metadata: { userId: '123' }
});

// Generate presigned URL
const presignedUrl = await storage.getPresignedUploadUrl('uploads/file.pdf', {
  expiresIn: 3600,
  contentType: 'application/pdf'
});

🏒 Organizations Module

The Organizations module provides complete multi-tenancy support:

Features

  • Organization Management: CRUD operations for organizations
  • Team Management: Add/remove members with roles
  • Invite System: Email-based invitations with secure tokens
  • Permission System: Role-based access control
  • Multi-tenancy: Data isolation between organizations

Usage

import { useOrganizations, useCreateOrganization } from '@/lib/trpc';

function OrganizationsPage() {
  const { data: organizations } = useOrganizations();
  const createOrg = useCreateOrganization();

  const handleCreate = async (data) => {
    await createOrg.mutateAsync(data);
  };

  return (
    <div>
      {organizations?.data.map(org => (
        <div key={org.id}>{org.name}</div>
      ))}
    </div>
  );
}

πŸ”§ Development Scripts

Setup Scripts

bun run setup:env          # Setup environment variables
bun run setup:env:complete # Complete environment setup
bun run setup:neon         # Setup Neon database
bun run setup:webhook      # Setup webhooks
bun run setup:storage      # Setup Cloudflare R2 storage

Database Scripts

bun run db:migrate         # Run migrations
bun run db:generate        # Generate migration
bun run db:push           # Push schema changes
bun run db:studio         # Open Drizzle Studio
bun run db:setup          # Setup database
bun run db:reset          # Reset database

Seeder Scripts

bun run seed:run          # Run all seeders
bun run seed:list         # List seeders
bun run seed:help         # Show help

Supabase Scripts

bun run supabase:local    # Start local Supabase
bun run supabase:remote   # Connect to remote Supabase
bun run supabase:status   # Check Supabase status

πŸš€ Deployment

Vercel Deployment

Deploy with Vercel

Environment Variables

Required environment variables for deployment:

# Database
DATABASE_URL=your_neon_database_url
USE_DRIZZLE=true

# Supabase (Auth only)
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key

# Email
RESEND_API_KEY=your_resend_api_key

# Redis
UPSTASH_REDIS_REST_URL=your_upstash_url
UPSTASH_REDIS_REST_TOKEN=your_upstash_token

# Analytics
OPENPANEL_SECRET_KEY=your_openpanel_key
NEXT_PUBLIC_OPENPANEL_CLIENT_ID=your_openpanel_client_id

# Error Tracking
SENTRY_AUTH_TOKEN=your_sentry_auth_token
NEXT_PUBLIC_SENTRY_DSN=your_sentry_dsn
SENTRY_ORG=your_sentry_org
SENTRY_PROJECT=your_sentry_project

# Background Jobs
TRIGGER_API_KEY=your_trigger_api_key
TRIGGER_API_URL=https://api.trigger.dev

# Cloudflare R2 Storage
R2_ACCOUNT_ID=your_r2_account_id
R2_ACCESS_KEY_ID=your_r2_access_key_id
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key
R2_BUCKET_NAME=your_r2_bucket_name
R2_REGION=auto
R2_ENDPOINT=https://your_account_id.r2.cloudflarestorage.com

## πŸ“š Documentation

- [Database Seeding](./docs/database-seeding.md)
- [Discord OAuth Setup](./docs/discord-oauth-setup.md)
- [Supabase Environment Setup](./docs/supabase-environment-setup.md)
- [Webhook Setup](./docs/webhook-setup.md)
- [Storage System](./packages/storage/README.md)

## 🀝 Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request

## πŸ“„ License

This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details.

## πŸ™ Acknowledgments

- Based on [Midday](https://midday.ai) and the original [V1](https://v1.run) boilerplate
- Enhanced with modern database architecture and development practices
- Built with the latest technologies and best practices

## πŸ”” Notification System

The application includes a comprehensive notification system with the following features:

### Notification Features
- **Real-time Notifications**: Dropdown in navbar with unread count badge
- **Multiple Types**: Info, success, warning, error, invite, mention
- **Rich Content**: Support for organization and post references
- **Status Management**: Mark as read/unread, archive/unarchive
- **Detailed View**: Modal with full notification details
- **Bulk Actions**: Mark all as read functionality
- **Filtering**: View all, unread, or archived notifications

### Notification Components
```tsx
import { NotificationDropdown, NotificationItem, NotificationDetailModal } from '@/components/notifications';

// Dropdown in navbar
<NotificationDropdown />

// Individual notification item
<NotificationItem notification={notification} onMarkAsRead={handleMarkAsRead} />

// Detail modal
<NotificationDetailModal notification={notification} isOpen={isOpen} onClose={onClose} />

Notification API Endpoints

// Get notifications with filters
const { data } = useNotifications({ limit: 20, includeRead: false });

// Get unread count
const { data } = useUnreadNotificationsCount();

// Mark as read/unread
const markAsRead = useMarkNotificationAsRead();
const markAsUnread = useMarkNotificationAsUnread();

// Archive/unarchive
const archive = useArchiveNotification();
const unarchive = useUnarchiveNotification();

// Delete notification
const deleteNotification = useDeleteNotification();

Notification Routes

  • /notifications - Full notifications management page
  • Navbar dropdown - Quick access to recent notifications

Notification Database Schema

notifications (
  id: uuid PRIMARY KEY,
  userId: uuid REFERENCES users(id),
  title: text NOT NULL,
  message: text NOT NULL,
  type: text NOT NULL,
  isRead: boolean DEFAULT false,
  isArchived: boolean DEFAULT false,
  organizationId: uuid REFERENCES organizations(id),
  postId: uuid REFERENCES posts(id),
  metadata: jsonb,
  createdAt: timestamp DEFAULT now(),
  updatedAt: timestamp DEFAULT now(),
  readAt: timestamp
)

πŸ‘€ Profile Management

The application includes a comprehensive profile management system with the following features:

Profile Features

  • Profile Information: Edit name, bio, website, location, avatar URL
  • Security Settings: Change password with current password verification
  • Account Management: Delete account with confirmation dialog
  • User Overview: Display account statistics and metadata

Profile Components

import { ProfileForm, ChangePasswordForm, DeleteAccountForm } from '@/components/profile';

// Profile editing form
<ProfileForm />

// Password change form with validation
<ChangePasswordForm />

// Account deletion with confirmation dialog
<DeleteAccountForm />

Profile Page Structure

  • Account Overview: User info, email verification status, member since date
  • Profile Tab: Edit personal information and preferences
  • Security Tab: Change password with current password verification
  • Danger Zone: Delete account with confirmation and warnings
  • Quick Actions: Links to dashboard, organizations, and posts

Profile Routes

  • /profile - Main profile management page
  • /dashboard - Dashboard with profile link

Profile API Endpoints

// Update profile information
const { mutate: updateProfile } = useUpdateProfile();

// Change password
const { mutate: changePassword } = useChangePassword();

// Delete account
const { mutate: deleteAccount } = useDeleteAccount();

πŸ†• What's Different from Original V1

Major Improvements

  1. Database Decoupling: Separated database from Supabase, now using Neon PostgreSQL
  2. Type-safe ORM: Replaced Supabase database with Drizzle ORM
  3. tRPC BFF: Type-safe API layer implemented as Backend for Frontend within the app
  4. Advanced Seeder System: Laravel-inspired seeding with faker.js
  5. Multi-tenancy: Complete organizations module with team management
  6. Storage System: Cloudflare R2 integration with image transformations
  7. Notification System: Comprehensive notification system with real-time updates
  8. Enhanced Scripts: Automated setup and provisioning scripts
  9. Better DX: Improved development experience with Bun and modern tooling
  10. Comprehensive Documentation: Detailed docs for all features

Technical Improvements

  • Performance: Optimized database queries and batch operations
  • Type Safety: End-to-end TypeScript support with tRPC BFF
  • Scalability: Serverless database with automatic scaling
  • Security: Enhanced authentication and permission systems
  • Storage: S3-compatible object storage with image processing
  • Notifications: Real-time notification system with rich content support
  • API Design: BFF pattern for optimized frontend-backend communication
  • Maintainability: Better code organization and separation of concerns

This enhanced version maintains all the benefits of the original V1 while adding modern database architecture, type-safe BFF API, multi-tenancy support, comprehensive storage system, and improved development experience! πŸš€

About

An open-source starter kit based on Midday.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 57.2%
  • MDX 39.0%
  • JavaScript 2.9%
  • Shell 0.3%
  • HTML 0.2%
  • PLpgSQL 0.2%
  • CSS 0.2%