Documentation Index Fetch the complete documentation index at: https://docs.edgespark.dev/llms.txt
Use this file to discover all available pages before exploring further.
EdgeSpark includes built-in user authentication. Your server code reads the current user through auth from edgespark/http. For browser login and sign-up flows, use @edgespark/web and the auth UI guide .
Read the current user
import { auth } from "edgespark/http" ;
import { Hono } from "hono" ;
const app = new Hono (). get ( "/api/me" , ( c ) => {
return c . json ({
id: auth . user . id ,
email: auth . user . email ,
name: auth . user . name ,
});
});
export default app ;
Store data linked to a user
import { db } from "edgespark" ;
import { auth } from "edgespark/http" ;
import { Hono } from "hono" ;
import { posts } from "@defs" ;
const app = new Hono (). post ( "/api/posts" , async ( c ) => {
const body = await c . req . json <{ title : string ; content : string }>();
const [ post ] = await db
. insert ( posts )
. values ({
title: body . title ,
content: body . content ,
authorId: auth . user . id ,
})
. returning ();
return c . json ( post , 201 );
});
export default app ;
Handle optional auth in public routes
import { db } from "edgespark" ;
import { auth } from "edgespark/http" ;
import { eq } from "drizzle-orm" ;
import { Hono } from "hono" ;
import { likes , posts } from "@defs" ;
const app = new Hono (). get ( "/api/public/feed" , async ( c ) => {
const allPosts = await db . select (). from ( posts ). where ( eq ( posts . published , 1 ));
if ( auth . user ) {
const liked = await db
. select ({ postId: likes . postId })
. from ( likes )
. where ( eq ( likes . userId , auth . user . id ));
const likedIds = new Set ( liked . map (( item ) => item . postId ));
return c . json ( allPosts . map (( post ) => ({ ... post , liked: likedIds . has ( post . id ) })));
}
return c . json ( allPosts );
});
export default app ;
Verify webhooks yourself
Routes under /api/webhooks/* skip session validation, so verify signatures in your own code:
import { secret } from "edgespark" ;
import { Hono } from "hono" ;
const app = new Hono (). post ( "/api/webhooks/stripe" , async ( c ) => {
const signature = c . req . header ( "stripe-signature" ) ?? "" ;
const rawBody = await c . req . text ();
const signingSecret = secret . get ( "STRIPE_WEBHOOK_SECRET" ) ?? "" ;
const encoder = new TextEncoder ();
const key = await crypto . subtle . importKey (
"raw" ,
encoder . encode ( signingSecret ),
{ name: "HMAC" , hash: "SHA-256" },
false ,
[ "verify" ]
);
const sigParts = Object . fromEntries (
signature . split ( "," ). map (( part ) => part . split ( "=" ) as [ string , string ])
);
const signedPayload = ` ${ sigParts . t } . ${ rawBody } ` ;
const valid = await crypto . subtle . verify (
"HMAC" ,
key ,
hexToBytes ( sigParts . v1 ?? "" ),
encoder . encode ( signedPayload )
);
if ( ! valid ) return c . json ({ error: "Invalid signature" }, 401 );
return c . json ({ received: true });
});
export default app ;
function hexToBytes ( hex : string ) : Uint8Array {
const bytes = new Uint8Array ( hex . length / 2 );
for ( let i = 0 ; i < hex . length ; i += 2 ) {
bytes [ i / 2 ] = parseInt ( hex . slice ( i , i + 2 ), 16 );
}
return bytes ;
}
See also
auth reference The runtime auth API and when auth.user is available.
Path-based auth How URL path conventions enforce login requirements without middleware.