Skip to main content

Development Guidelines & Common Pitfalls

This document provides best practice guidelines for development based on the Lovrabet platform.

Prerequisite Reading

If you're not yet familiar with Lovrabet's tool ecosystem, we recommend reading Developer Toolchain Overview first.


Core Philosophy

AI handles standardized repetitive work, humans focus on creative value output

  • AI's strengths - Rapid generation of standardized, zero-error basic features
  • Human strengths - Creative thinking, industry insights, user empathy
  • Perfect collaboration - AI provides infrastructure, humans build unique value

Application Scenarios

1. Mini Program Ecosystem Expansion

Build WeChat Mini Programs and Alipay Mini Programs based on enterprise data:

import { createClient } from "@lovrabet/sdk";

const client = createClient({
appCode: "your-enterprise-app",
token: wx.getStorageSync("userToken"),
});

const customerData = await client.models.customers.filter({
region: "East China",
level: "VIP",
});

2. Workflow Automation

Build complex approval processes and data processing pipelines:

const approvalWorkflow = {
trigger: await client.models.orders.filter({ status: "pending" }),
conditions: [
{ field: "amount", operator: ">", value: 10000 },
{ field: "customer.level", operator: "=", value: "VIP" },
],
actions: ["sendNotification", "createApprovalTask", "updateOrderStatus"],
};

3. Multi-System Integration Hub

Connect Lovrabet with existing enterprise systems (ERP, CRM, OA):

const dataHub = {
lovrabet: await lovrabetClient.models.products.filter(),
erp: await erpConnector.getInventory(),
crm: await crmConnector.getCustomers(),
synchronize: () => {
// Complex data sync and transformation logic
},
};

Client Management

Frontend: Singleton Pattern Reuse

// Recommended: Singleton pattern, global reuse
// src/api/client.ts
import { createClient } from "@lovrabet/sdk";

export const client = createClient({
appCode: "your-app-code",
});

// Use in components
import { client } from "@/api/client";
// Not recommended: Creating new instance each time
function MyComponent() {
const client = createClient({ appCode: "..." }); // Creates new instance on every render
}

Backend: Spring Bean Singleton

// Recommended: Use @Bean singleton
@Configuration
public class LovrabetConfig {
@Bean
public LovrabetSDKClient lovrabetSDKClient() {
return new LovrabetSDKClient(accessKey, baseUrl);
}
}

Security

AccessKey Management

# Use environment variables
export LOVRABET_ACCESS_KEY="ak-your-access-key"
// Never hardcode AccessKey in frontend
const client = createClient({
accessKey: "ak-xxx", // Dangerous! Will be exposed in browser
});

// Use Cookie or Token in browser
const client = createClient({
appCode: "your-app-code",
// Automatically uses Cookie authentication
});

Sensitive Data Masking

// Frontend: Mask phone number
const maskPhone = (phone: string) => {
return phone.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
};
// 138****8000
// Backend: Log masking
String maskedPhone = phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
log.info("Customer phone: {}", maskedPhone);

Performance Optimization

Pagination and Debouncing

// Use pagination
const { data } = await client.models.customers.filter({
currentPage: 1,
pageSize: 20,
});

// Debounce search
import { debounce } from "lodash-es";

const handleSearch = debounce(async (keyword) => {
await client.models.customers.filter({ searchKeyword: keyword });
}, 300);

Code Splitting

// Route lazy loading
import { lazy } from "react";

const CustomerAnalysis = lazy(() => import("./pages/CustomerAnalysis"));

Backend Caching

// Use Caffeine cache
private final Cache<String, Object> cache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();

Error Handling

Frontend Unified Handling

try {
const result = await client.models.customers.filter(params);
if (result.success) {
setData(result.data);
} else {
message.error(result.message);
}
} catch (error) {
console.error("API call failed:", error);
message.error("Network error, please try again later");
}

Backend Retry Mechanism

public <T> LovrabetResult<T> executeWithRetry(
Supplier<LovrabetResult<T>> operation, int maxRetries) {
for (int attempt = 0; attempt <= maxRetries; attempt++) {
try {
LovrabetResult<T> result = operation.get();
if (result.isSuccess()) return result;
Thread.sleep((long) Math.pow(2, attempt) * 1000);
} catch (Exception e) {
if (attempt == maxRetries) throw new RuntimeException("Retry failed", e);
}
}
return null;
}

Logging Standards

Structured Logging

@Slf4j
public class DataService {
public void createData(Map<String, Object> data) {
long startTime = System.currentTimeMillis();

log.info("Start operation - operation={}, dataSize={}", "create", data.size());

LovrabetResult<String> result = sdkClient.create(request);
long duration = System.currentTimeMillis() - startTime;

if (result.isSuccess()) {
log.info("Operation success - id={}, duration={}ms", result.getData(), duration);
} else {
log.error("Operation failed - code={}, duration={}ms", result.getResultCode(), duration);
}
}
}

Testing Strategy

Frontend Unit Testing

import { render, screen, waitFor } from "@testing-library/react";

test("should load customers", async () => {
render(<CustomerList />);
await waitFor(() => {
expect(screen.getByText("Zhang San")).toBeInTheDocument();
});
});

Backend Integration Testing

@SpringBootTest
public class DataServiceIntegrationTest {
@Autowired
private DataService dataService;

@Test
public void testGetCustomers() {
List<Map<String, Object>> customers = dataService.getCustomers(1, 10);
assertNotNull(customers);
assertTrue(customers.size() > 0);
}
}

Deployment Recommendations

Frontend Deployment

lovrabet build
# Output in dist/ directory, deploy to CDN

Nginx Configuration:

server {
listen 80;
root /var/www/your-app/dist;

location / {
try_files $uri $uri/ /index.html;
}

location ~* \.(js|css|png|jpg|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}

Backend Docker Deployment

FROM openjdk:11-jre-slim
WORKDIR /app
COPY target/myapp.jar app.jar
ENV LOVRABET_ACCESS_KEY=""
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Health Check

@GetMapping("/health/lovrabet")
public Map<String, Object> checkHealth() {
Map<String, Object> health = new HashMap<>();
try {
long start = System.currentTimeMillis();
LovrabetResult<?> result = sdkClient.getDatasetCodeList(request);
health.put("status", result.isSuccess() ? "UP" : "DOWN");
health.put("responseTime", (System.currentTimeMillis() - start) + "ms");
} catch (Exception e) {
health.put("status", "DOWN");
health.put("error", e.getMessage());
}
return health;
}

Summary

Practice AreaKey Points
Client ManagementUse singleton pattern for both frontend and backend
SecurityNever hardcode AccessKey in frontend
PerformancePagination, caching, code splitting
Error HandlingUnified handling + retry mechanism
LoggingStructured logging, sensitive data masking
TestingUnit tests + integration tests
DeploymentHealth checks, containerization