Astro Actions Demo
How Astro Actions Work
Astro Actions provide a type-safe way to define server-side functions that can be called from both server and client code.
They are automatically exposed at the /_actions endpoint.
Key Features:
- Type-safe with Zod validation
- Accessible via HTTP POST requests to
/_actions/[actionName] - Can be called from both server (SSR) and client code
- Automatic error handling and validation
Demo 1: Standard SSR Action
This action is executed on the server during SSR and returns server information.
{
"message": "This is a standard SSR action",
"executedAt": "2025-12-11T12:13:14.501Z",
"serverType": "Astro SSR"
} View HTTP API Example
HTTP Request:
POST http://localhost:8443/_actions/getServerInfo
Response (Array Format):
[
{
"message": 1,
"executedAt": 2,
"serverType": 3,
"nodeVersion": 4
},
"This is a standard SSR action",
"2025-06-15T18:49:00.194Z",
"Astro SSR",
"v22.15.1"
] Source Code:
// src/actions/index.ts
getServerInfo: defineAction({
handler: async () => {
return {
message: 'This is a standard SSR action',
executedAt: new Date().toISOString(),
serverType: 'Astro SSR',
nodeVersion: process.version
}
}
}) Demo 2: Environment Variable with Timestamp
This action reads the TEST environment variable and returns it with various time formats.
{
"environmentValue": "Environment variable not found",
"timestamp": "2025-12-11T12:13:14.501Z",
"unixTime": 1765455194501,
"formattedTime": "12/11/2025, 12:13:14 PM"
} View HTTP API Example
HTTP Request:
POST http://localhost:8443/_actions/getEnvWithTime
Response (Array Format):
[
{
"environmentValue": 1,
"timestamp": 2,
"unixTime": 3,
"formattedTime": 4
},
"hello_boii",
"2025-06-15T18:51:38.682Z",
1750013498682,
"6/15/2025, 8:51:38 PM"
] Source Code:
// src/actions/index.ts
getEnvWithTime: defineAction({
handler: async () => {
const testEnv = import.meta.env.TEST || 'Environment variable not found'
return {
environmentValue: testEnv,
timestamp: new Date().toISOString(),
unixTime: Date.now(),
formattedTime: new Date().toLocaleString()
}
}
}) Demo 3: Delayed Server Action
This action simulates a long-running process with configurable delay (100-5000ms).
View HTTP API Example
HTTP Request:
POST http://localhost:8443/_actions/delayedAction
Request Body:
{
"delay": 1000
} Response (Array Format):
[
{
"message": 1,
"requestedDelay": 2,
"actualDuration": 3,
"startedAt": 4,
"completedAt": 5
},
"Action completed after delay",
1000,
1001,
"2025-06-15T18:53:27.711Z",
"2025-06-15T18:53:28.712Z"
] Source Code:
// src/actions/index.ts
delayedAction: defineAction({
input: z.object({
delay: z.number().min(100).max(5000).default(2000)
}),
handler: async ({ delay }) => {
const startTime = Date.now()
// Simulate processing with delay
await new Promise(resolve => setTimeout(resolve, delay))
const endTime = Date.now()
return {
message: 'Action completed after delay',
requestedDelay: delay,
actualDuration: endTime - startTime,
startedAt: new Date(startTime).toISOString(),
completedAt: new Date(endTime).toISOString()
}
}
}) Additional Actions Available
The demo includes several more actions that showcase different features like input validation and error handling.
updateUserProfile Action
Demonstrates Zod input validation with required and optional fields.
View HTTP API Example
HTTP Request:
POST http://localhost:8443/_actions/updateUserProfile
Request Body:
{
"name": "John Doe",
"email": "john@example.com",
"age": 25
} Response (Array Format):
[
{
"success": 1,
"message": 2,
"userData": 3,
"updatedAt": 7
},
true,
"Profile updated for John Doe",
{
"name": 4,
"email": 5,
"age": 6
},
"John Doe",
"john@example.com",
25,
"2025-06-15T18:54:15.450Z"
] Source Code:
updateUserProfile: defineAction({
input: z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().min(18).optional()
}),
handler: async ({ name, email, age }) => {
// Simulate database operation
console.log('Updating user profile:', { name, email, age })
return {
success: true,
message: `Profile updated for ${name}`,
userData: { name, email, age },
updatedAt: new Date().toISOString()
}
}
}) sendNotification Action
Shows error handling and enum validation (try sending a message with "fail" in it).
View HTTP API Example
HTTP Request:
POST http://localhost:8443/_actions/sendNotification
Request Body:
{
"message": "Hello world!",
"type": "info"
} Response (Array Format):
[
{
"success": 1,
"notificationId": 2,
"message": 3,
"sentAt": 4
},
true,
"0.q77wegh82p9",
"INFO: Hello world!",
"2025-06-15T18:55:25.854Z"
] Source Code:
sendNotification: defineAction({
input: z.object({
message: z.string(),
type: z.enum(['info', 'warning', 'error'])
}),
handler: async ({ message, type }) => {
// Simulate some processing
await new Promise(resolve => setTimeout(resolve, 1000))
if (message.includes('fail')) {
throw new Error('Notification failed to send')
}
return {
success: true,
notificationId: Math.random().toString(36),
message: `${type.toUpperCase()}: ${message}`,
sentAt: new Date().toISOString()
}
}
}) Ready for Database Integration
These actions are currently using in-memory data and hardcoded values. They're designed to be easily extended with CloudFlare D1 or other databases to persist and retrieve real data.