Technology specific implementation examples
Check the functions provided by Cake20 through short source code and actual execution results.
Cake20 View pages and components
// app/components/GreetingCard.tsx
export type Props = { name: string };
export default ({ name }: Props) => <Card>Hello, {name}</Card>;
// app/pages/index.tsx
export default () => <GreetingCard name="cafe" />;Result
A ‘Hello, Cafe’ card will appear on the home screen. Component import is not required.
Cake20 UI and Tailwind CSS
export default () => (
<Button icon="i-lucide-save" class="mt-4" onClick={save}>save</Button>
);Result
You will see a Cake20 UI button with a Lucide save icon. No need for U prefix and package installation.
WYSIWYG Editor
export const data = {
content: "<h2>Today’s record</h2><p>Write down the contents.</p>",
};
export default () => (
<Editor bind={data.content} image={false} mention={false} />
);Result
You'll see a Tiptap-based formatting editor that syncs bi-directionally with your HTML strings.
DragList drag sorting
export default () => (
<DragList bind={data.cards} group="tasks" onEnd={saveOrder}>
{data.cards.map((card) => <Card key={card.id}>{card.title}</Card>)}
</DragList>
);Result
You can grab all the cards and change their order or move them to another list in the same group.
Website visibility settings
// package.json
{
"title": "Neighborhood cafe",
"description": "Introducing today’s menu.",
"timezone": "Asia/Seoul",
"lang": "en"
}Result
Document title and public meta information are applied, and server time calculation uses the Seoul standard.
Responsive Store
// app/stores/cart.store.ts
export const config = { persist: "local" } as const;
export default {
count: 0,
add() { this.count += 1; }
};
// app/pages/index.tsx
export default () => (
<Button onClick={() => store.cart.add()}>{store.cart.count}</Button>
);Result
When you press the button, the number increases and is recovered from localStorage even when you reopen the browser.
Provide Context to descendants
// app/components/ThemePanel.tsx
export const data = { theme: "dark" as "light" | "dark" };
export const context = { theme: () => data.theme };
export default () => <ThemeLabel />;
// app/components/ThemeLabel.tsx
const theme = useContext<"light" | "dark">("theme");
export default () => <p>Current theme: {theme()}</p>;Result
A descendant uses the nearest parent context value without prop forwarding. Use context for UI subtree state and a store for global or persistent state.
API and input validation
// server/api/memos.post.ts
export const config = {
filter: { title: z.string().trim().min(1).max(80) },
sample: { title: "first note" }
};
export default async (data: Input<typeof config.filter>) =>
db.memo.create({ data });Result
A POST /api/memos is generated and invalid input is blocked with a 400 response before DB execution.
Inquiry form storage box
// server/api/contact.post.ts
export default defineApi(async (input, { request }) =>
form.submit(request, {
name: "contact",
consent: input.consent === true,
data: { email: input.email, message: input.message }
})
);Result
Inquiries are stored in a dedicated website archive, and speed limit, capacity limit, and consent information are applied together.
Prisma database model
// server/db/memo.db.ts
export const Memo = {
id: z.id(),
title: z.string().max(80),
createdAt: z.date().defaultNow().timestamp()
};Result
The Memo table and Prisma access object db.memo are created. Use one db.ts file per table.
Initial data and preview samples
// server/db/memo.db.ts
export const Memo = {
id: z.string().id().max(30),
title: z.string().max(100)
};
export const seed = async () => [
{ id: "first", title: "First note" },
{ id: "shopping", title: "Grocery shopping" }
];Result
Cake20 builds Preview JSON from the current rows and upserts only new or changed seeds.
Reusable SQL functions
// server/db/memo.sql.ts
export const recentMemos = db.sql(
z.object({ id: z.string(), title: z.string() }),
() => sql`SELECT id, title FROM "Memo" ORDER BY "createdAt" DESC LIMIT 5`
);
const rows = await db.sql.recentMemos();Result
An array of verified recent notes is returned, and the same function can be reused in API·Hook·Task.
Login and permissions
// server/api/me.get.ts
export default async (_data: unknown, context: ApiContext) => {
const user = await auth.require(context.request, { roles: ["admin"] });
return { email: user.email };
};Result
Administrators receive an email, non-logged users receive a 401 response, and unauthorized users receive a 403 response.
Routes, WebSockets and SSE
// server/routes/notice.sse.ts
export default () => ({
event: "notice",
data: { text: "Your order is ready." }
});
// server/routes/chat.ws.ts
export default { onMessage(peer, message) { peer.publish("room", message); } };Result
The browser receives server notifications in /notice and real-time messages from the same room in /chat.
Hook, Task, Job and Schedule
// server/hooks/order.hook.ts
export default (order: Order) => console.log(order.id);
// server/tasks/cleanup.task.ts
export default async () => ({ removed: await db.memo.deleteMany() });
// server/tasks/daily.job.ts
export const config = { cron: "0 0 * * *" };
export default async () => db.report.create({ data: { day: textDate(now()) } });Result
Event hooks, manual tasks, and daily midnight jobs are managed with independent files and execution history.
Redis-based asynchronous Job
// server/api/report.post.ts
const work = await job.report({ month: "2026-08" });
return { id: work.id };
// status inquiry
const state = await job.$get(work.id);Result
The API immediately returns the job ID, and the server job manages retries and status in the website-specific Redis Queue.
Alarms, emails and payments
await mail.send({ to: "[email protected]", subject: "Sign up completed", text: "welcome." });
if (telegram.active) await telegram.send("A new order has been registered.");
if (gmail.active) {
await gmail.send({ subject: "new order", text: "A new order has been registered." });
}
const ready = await payment.request({
orderId: "ORDER-1",
orderName: "strawberry cake",
amount: 12000,
returnUrl: "https://example.com/pay/success",
cancelUrl: "https://example.com/pay/fail"
});Result
Send notifications to site administrator Telegram·Gmail and SMTP and return payment request information.
Files and Object Storage
const file = await storage.put("images/menu.webp", body);
return { url: storage.url(file.path) };Result
A publishable image URL is returned regardless of local and Object Storage settings.
Create Excel XLSX
const rows = [["Order"], ["Strawberry cake"]];
return excel.download("orders.xlsx", rows);Result
Simple rows are returned as an XLSX download Response without persisting them to storage.
executable test
test("Note list", async () => {
const data = await fetchGet<{ items: unknown[] }>("/api/memos");
expect(data.items.length).toBeGreaterThan(0);
});Result
The inspection build actually calls the API, and the pass/fail results are displayed in the editor test console.