Codebase Architecture Analysis: LIFF Carbon Offset Application
π Navigation: π INDEX | π Analysis Home | π Diary | π Reports
Related Reads: Git History Analysis | LIFF Implementation Review | Environmental Impact Assessment
System Architecture Overviewβ
High-Level Architectureβ
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β LINE App β β Cloudflare β β Blockchain β
β β β Infrastructure β β Networks β
β βββββββββββββ β β β β β
β β LIFF App ββββΌβββββΌββΊ Next.js Pages β β βββββββββββββββ β
β β Frontend β β β βββββββββββββββ β β β JBC Chain β β
β βββββββββββββ β β β Hono β β β β (Chain 8899)β β
β β β β Workers β ββββββΌββΊ NFT Contractsβ β
β βββββββββββββ β β βββββββββββββββ β β βββββββββββββββ β
β β LINE Bot ββββΌβββββΌββΊ KV Storage β β β
β β Webhook β β β βββββββββββββββ β β βββββββββββββββ β
β βββββββββββββ β β β R2 Storage β β β β Sichang β β
βββββββββββββββββββ β β (Images) β β β β Chain 5151 β β
β βββββββββββββββ β β β (Backup) β β
β βββββββββββββββ β β βββββββββββββββ β
β β D1 Database β β βββββββββββββββββββ
β β (SQLite) β β
β βββββββββββββββ β
ββββββββββββββββββββ
Technology Stack Analysisβ
Frontend Layer (Next.js 15.3.2)
// Core Technologies
- React 19.0.0 // Latest React with concurrent features
- Next.js 15.3.2 // App directory, server components
- Tailwind CSS 3.4.17 // Utility-first styling
- TypeScript 5.x // Type safety throughout
// LINE Integration
- @line/liff 2.26.0 // LINE Frontend Framework
- LINE Messaging API // Webhook integration
// Blockchain Integration
- Viem 2.30.6 // Ethereum-compatible client
- Wagmi 2.15.6 // React hooks for Web3
- @thirdweb-dev/sdk // Simplified blockchain operations
Backend Layer (Cloudflare Workers)
// Core Framework
- Hono 4.7.9 // Fast web framework for edge
- Cloudflare Workers // Serverless edge computing
// Storage Strategy
- Cloudflare KV // Global key-value store
- Cloudflare R2 // S3-compatible object storage
- Cloudflare D1 // SQLite at the edge
- Drizzle ORM 0.44.2 // Type-safe database operations
Integration Layer
// Payment Processing
- LINE Webhook API // Receipt image processing
- Credit card gateways // External payment processing
// Blockchain Networks
- JBC Chain (8899) // Primary NFT deployment
- Sichang Chain (5151) // Backup/testing network
- Thirdweb Engine // Wallet management service
Frontend Architecture Deep Diveβ
Next.js App Directory Structureβ
src/app/
βββ (auth)/ # Authentication guard routes
βββ admin/ # Admin panel (protected)
β βββ layout.tsx # Admin-specific layout & navigation
β βββ guests/ # Guest management
β β βββ page.tsx # Guest list with pagination
β β βββ [id]/ # Individual guest detail
β βββ payments/ # Payment verification interface
β βββ blockchain/ # NFT transfer monitoring
β βββ event-report/ # Analytics dashboard
β βββ qr-generator/ # QR code generation tools
βββ carbon-offset/ # Public carbon offset calculator
βββ carbon-offset-public/ # Shareable offset pages
βββ dashboard/ # User dashboard
βββ dinner-talk/ # Event registration
β βββ [id]/ # Individual event pages
βββ preview/ # Content preview mode
βββ special/ # Special access bypass
βββ api/ # API routes (forwarding to Workers)
βββ carbon/offset/ # Carbon offset processing
βββ dinner-talk/ # Event management
βββ wallet/ # Blockchain wallet operations
Component Architectureβ
Core Component Patterns
// High-level component organization
src/components/
βββ AdminLoginOverlay.tsx # Authentication guard
βββ ChainSelector.tsx # Multi-blockchain switching
βββ NFTTransferStatus.tsx # Real-time transfer monitoring
βββ QRCodeDisplay.tsx # QR code generation & display
βββ ShareButton.tsx # Social sharing functionality
βββ Toast.tsx # Notification system
βββ providers.tsx # Context providers wrapper
// Context Management
src/contexts/
βββ AdminAuthContext.tsx # Admin session management
βββ ToastContext.tsx # Global notification state
// Custom Hooks
src/hooks/
βββ useWallet.ts # Blockchain wallet integration
State Management Strategy
// Local state with React hooks (no global state library)
const [loadingStates, setLoadingStates] = useState({
fetchingGuests: false,
approvingPayment: false,
transferringNFT: false,
generatingQR: false
});
// Context for shared state
const AdminAuthContext = createContext({
isAuthenticated: false,
login: () => {},
logout: () => {},
lastActivity: Date.now()
});
Backend Architecture Deep Diveβ
Cloudflare Workers Structureβ
workers/
βββ index.ts # Main worker entry point
βββ routes/ # API route handlers
β βββ admin.ts # Admin operations (1074 changes!)
β βββ admin-db.ts # Database admin operations
β βββ auth.ts # Authentication & wallet creation
β βββ carbon.ts # Carbon offset processing
β βββ carbon-data.ts # Environmental data management
β βββ dashboard.ts # Dashboard statistics
β βββ dinner-talk.ts # Event management
β βββ line-webhook.ts # LINE message processing
β βββ profile.ts # User profile management
β βββ registration.ts # Event registration
β βββ test.ts # Development testing
β βββ wallet.ts # Blockchain operations
βββ services/ # Business logic services
β βββ nft-transfer.service.ts # NFT transfer orchestration
βββ db/ # Database schema & migrations
βββ schema.ts # Drizzle schema definitions
βββ migrations/ # SQL migration files
API Architecture Patternsβ
RESTful Endpoint Organization
// Admin operations (most complex route file)
app.get('/admin/guests', authMiddleware, paginatedGuestList);
app.get('/admin/guest/:id', authMiddleware, guestDetail);
app.post('/admin/verify-payment', authMiddleware, paymentVerification);
app.post('/admin/reject-payment', authMiddleware, paymentRejection);
app.get('/admin/receipts/:fileName', authMiddleware, receiptImageServing);
app.get('/admin/stats', authMiddleware, dashboardStatistics);
// Carbon offset operations
app.post('/carbon/offset', carbonOffsetPurchase);
app.get('/carbon/offsets/:userId', userOffsetHistory);
app.get('/carbon-data/services', availableServices);
app.get('/carbon-data/service/:serviceId/:duration?', serviceCalculation);
// Blockchain operations
app.post('/wallet/create', walletCreation);
app.get('/wallet/balance/:address', walletBalance);
app.post('/nft/process-next', nftTransferProcessing);
Middleware Pipeline
// Authentication middleware
const authMiddleware = async (c: Context, next: () => Promise<void>) => {
const auth = c.req.header('Authorization');
if (!auth || !validateAdminCredentials(auth)) {
return c.json({ error: 'Unauthorized' }, 401);
}
await next();
};
// CORS middleware
app.use('*', cors({
origin: ['https://liff-carbon-offset-app.pages.dev'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization']
}));
Data Architecture & Storage Strategyβ
Multi-Storage Pattern Analysisβ
Cloudflare KV Usage (Fast Access)
// User sessions (global edge distribution)
await USER_KV.put(`user:${userId}`, JSON.stringify({
profile: userProfile,
lastActivity: Date.now(),
sessionId: generateSessionId()
}), { expirationTtl: 3600 });
// Guest registration data (quick lookup)
await GUESTS_KV.put(`guest:${guestId}`, JSON.stringify(guestData));
// Payment metadata (admin performance)
await EVENT_KV.put('payments_metadata', JSON.stringify(allPayments));
Cloudflare R2 Usage (Permanent Storage)
// Receipt images (permanent, large files)
await PAYMENT_RECEIPTS.put(`receipts/${userId}/${timestamp}.jpg`, imageBuffer, {
httpMetadata: {
contentType: 'image/jpeg',
cacheControl: 'public, max-age=31536000'
}
});
// QR code images (shareable content)
await PAYMENT_RECEIPTS.put(`qr-codes/${serviceId}-${amount}.png`, qrBuffer);
Cloudflare D1 Usage (Relational Queries)
// NFT transfer tracking (relational data)
export const nftTransfers = sqliteTable('nft_transfers', {
id: text('id').primaryKey(),
guestId: text('guest_id').notNull(),
tokenId: integer('token_id').notNull(),
chainId: integer('chain_id').notNull(),
status: text('status').notNull(), // pending, submitted, completed, failed
txHash: text('tx_hash'),
createdAt: text('created_at').default(sql`CURRENT_TIMESTAMP`),
completedAt: text('completed_at')
});
// Guest dinner talk registrations
export const dinnerTalkGuests = sqliteTable('dinner_talk_guests', {
id: text('id').primaryKey(),
userId: text('user_id').notNull(),
name: text('name').notNull(),
organization: text('organization'),
registeredAt: text('registered_at').default(sql`CURRENT_TIMESTAMP`),
checkedInAt: text('checked_in_at')
});
Data Flow Architectureβ
User Registration Flow
LINE User β LIFF Auth β User Profile Creation β Wallet Generation β Event Registration
β β β β β
LINE API β KV Storage β Thirdweb Engine β KV Storage β D1 Database
Payment Processing Flow
Receipt Upload β LINE Webhook β Image Download β R2 Storage β Admin Verification β NFT Minting
β β β β β β
LINE Bot β Cloudflare Worker β LINE API β R2 Bucket β KV Update β Blockchain
Admin Dashboard Flow
Admin Login β Authentication β Data Aggregation β Real-time Updates β Action Processing
β β β β β
Auth Context β Middleware β Multi-storage Query β Polling β API Calls
Integration Architectureβ
LINE Platform Integrationβ
LIFF (LINE Frontend Framework) Implementation
// Platform-specific initialization
const initializeLiff = async () => {
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
await liff.init({
liffId: process.env.NEXT_PUBLIC_LIFF_ID,
withLoginOnExternalBrowser: !isIOS // iOS requires internal browser
});
if (!liff.isLoggedIn()) {
liff.login({
redirectUri: window.location.href
});
}
// Get user profile for wallet creation
const profile = await liff.getProfile();
return profile;
};
LINE Bot Webhook Integration
// Secure webhook processing
app.post('/line-webhook', async (c) => {
// Verify LINE signature
const signature = c.req.header('X-Line-Signature');
const body = await c.req.text();
const expectedSignature = crypto
.createHmac('sha256', channelSecret)
.update(body)
.digest('base64');
if (signature !== expectedSignature) {
return c.json({ error: 'Invalid signature' }, 400);
}
// Process image messages (payment receipts)
const events = JSON.parse(body).events;
for (const event of events) {
if (event.type === 'message' && event.message.type === 'image') {
await processReceiptImage(event.message.id, event.source.userId);
}
}
return c.json({ success: true });
});
Blockchain Integration Architectureβ
Multi-Chain Support Pattern
// Chain configuration management
const SUPPORTED_CHAINS = {
8899: {
name: 'JIBCHAIN L1',
rpcUrl: 'https://rpc.jibchain.net',
explorerUrl: 'https://exp.jibchain.net',
contracts: {
carbonPass: '0x742d35Cc6634C0532925a3b8D1c9CEA03cF97c2a',
nftManager: '0x...'
},
isPrimary: true
},
5151: {
name: 'Sichang Testnet',
rpcUrl: 'https://rpc.sichang.net',
explorerUrl: 'https://explorer.sichang.net',
contracts: {
carbonPass: '0x456...',
nftManager: '0x789...'
},
isPrimary: false
}
};
// Unified blockchain operations
class BlockchainService {
async mintCarbonNFT(userId: string, amount: number, chainId: number = 8899) {
const chain = SUPPORTED_CHAINS[chainId];
const client = createWalletClient({
chain: {
id: chainId,
name: chain.name,
nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
rpcUrls: { default: { http: [chain.rpcUrl] } }
},
transport: http(chain.rpcUrl)
});
return await client.writeContract({
address: chain.contracts.carbonPass,
abi: carbonPassABI,
functionName: 'mint',
args: [userId, amount]
});
}
}
Performance Architectureβ
Edge Computing Optimization
// Smart caching strategy
const getCachedUserData = async (userId: string): Promise<UserData | null> => {
// Try KV first (edge cache)
const cached = await USER_KV.get(`user:${userId}`);
if (cached) {
return JSON.parse(cached);
}
// Fallback to D1 database
const userData = await db.query.users.findFirst({
where: eq(users.id, userId)
});
if (userData) {
// Cache for future requests
await USER_KV.put(`user:${userId}`, JSON.stringify(userData), {
expirationTtl: 3600
});
}
return userData;
};
// Real-time updates without WebSockets
const useRealTimeData = (fetchFunction: Function, interval: number = 30000) => {
const [data, setData] = useState(null);
const [lastUpdate, setLastUpdate] = useState(Date.now());
useEffect(() => {
const update = async () => {
const fresh = await fetchFunction();
setData(fresh);
setLastUpdate(Date.now());
};
update(); // Initial load
const timer = setInterval(update, interval);
return () => clearInterval(timer);
}, []);
return { data, lastUpdate, isStale: Date.now() - lastUpdate > interval };
};
Security Architectureβ
Authentication & Authorizationβ
// Multi-layer authentication
const authenticateRequest = async (request: Request): Promise<AuthResult> => {
// Layer 1: LIFF token validation
const liffToken = request.headers.get('X-LIFF-Token');
if (liffToken) {
const liffUser = await validateLiffToken(liffToken);
if (liffUser) return { type: 'user', userId: liffUser.sub };
}
// Layer 2: Admin credentials
const authHeader = request.headers.get('Authorization');
if (authHeader?.startsWith('Basic ')) {
const adminAuth = await validateAdminCredentials(authHeader);
if (adminAuth) return { type: 'admin', adminId: adminAuth.id };
}
return { type: 'anonymous' };
};
Data Security Patternsβ
// Sensitive data encryption
const encryptSensitiveData = (data: object): string => {
return CryptoJS.AES.encrypt(
JSON.stringify(data),
process.env.ENCRYPTION_KEY
).toString();
};
// Audit trail for admin actions
const logAdminAction = async (adminId: string, action: string, details: object) => {
await AUDIT_KV.put(`audit:${Date.now()}:${adminId}`, JSON.stringify({
adminId,
action,
details,
timestamp: new Date().toISOString(),
ip: getClientIP()
}));
};
Architecture Assessmentβ
Strengthsβ
- Edge-First Design - Optimal performance through Cloudflare edge network
- Multi-Storage Strategy - Right storage type for each data pattern
- Mobile-First Integration - Deep LINE platform integration
- Blockchain Abstraction - Multi-chain support with unified interface
- Production Security - Multi-layer authentication and audit trails
Complexity Areasβ
- Admin Route Complexity - 1074 changes indicate ongoing business logic evolution
- Payment Processing - Complex approval workflows for real-world scenarios
- Real-Time Updates - Polling-based approach instead of WebSockets
- Cross-Platform Handling - iOS vs Android LIFF behavior differences
Scalability Considerationsβ
- Edge computing enables global scale
- KV storage provides sub-millisecond access worldwide
- D1 database may become bottleneck for complex queries
- Polling approach limits real-time responsiveness
This architecture represents a production-grade LIFF application that successfully integrates mobile-first design, blockchain operations, environmental impact tracking, and complex payment processing workflows.
This analysis is based on examination of 278 commits, 8 tracked directories, and comprehensive codebase exploration of a real-world LIFF carbon offset application.