{"id":19726530,"url":"https://github.com/gustavocadev/qwik-lucia","last_synced_at":"2026-01-18T21:06:20.563Z","repository":{"id":223002485,"uuid":"758948560","full_name":"gustavocadev/qwik-lucia","owner":"gustavocadev","description":"Qwik Lucia 🔐⚡","archived":false,"fork":false,"pushed_at":"2024-08-23T19:14:02.000Z","size":189,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-13T21:18:48.997Z","etag":null,"topics":["drizzle-orm","examples","lucia","lucia-auth","neon","planetscale","qwik","qwik-city","turso","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/qwik-lucia","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gustavocadev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-17T14:50:34.000Z","updated_at":"2025-10-06T09:24:33.000Z","dependencies_parsed_at":"2024-08-23T20:32:36.109Z","dependency_job_id":"bab52ec1-f16c-4517-9b0b-4cd7477f1af4","html_url":"https://github.com/gustavocadev/qwik-lucia","commit_stats":null,"previous_names":["gustavocadev/qwik-lucia","salemgst/qwik-lucia"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/gustavocadev/qwik-lucia","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavocadev%2Fqwik-lucia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavocadev%2Fqwik-lucia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavocadev%2Fqwik-lucia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavocadev%2Fqwik-lucia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gustavocadev","download_url":"https://codeload.github.com/gustavocadev/qwik-lucia/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavocadev%2Fqwik-lucia/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28550550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T20:59:07.572Z","status":"ssl_error","status_checked_at":"2026-01-18T20:59:02.799Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drizzle-orm","examples","lucia","lucia-auth","neon","planetscale","qwik","qwik-city","turso","typescript"],"created_at":"2024-11-11T23:35:58.162Z","updated_at":"2026-01-18T21:06:20.547Z","avatar_url":"https://github.com/gustavocadev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Qwik Lucia\n\nQwik Lucia is a library that helps you to integrate [Lucia](https://lucia-auth.com/) with your Qwik project.\n\n- No more configuration\n\n## Installation\n\n```sh\nnpm i qwik-lucia\npnpm add qwik-lucia\nbun add qwik-lucia\nyarn add qwik-lucia\n```\n\n## Setup Qwik Lucia\n\nIn this example, we will use the `@lucia-auth/adapter-drizzle` adapter to connect to a PostgreSQL database.\n\n\u003e For simplicity, we won't show the imports that are not related to the `qwik-lucia` or `lucia` package.\n\n```ts\n// src/server/lucia.ts\nimport { Lucia } from 'lucia';\nimport { DrizzlePostgreSQLAdapter } from '@lucia-auth/adapter-drizzle';\nimport { qwikLuciaConfig } from 'qwik-lucia';\n\nconst adapter = new DrizzlePostgreSQLAdapter(db, sessionTable, userTable);\n\nexport const lucia = new Lucia(adapter, {\n  sessionCookie: {\n    attributes: {\n      // set to `true` when using HTTPS\n      secure: process.env.NODE_ENV === 'production',\n    },\n  },\n  getUserAttributes: (attributes) =\u003e {\n    return {\n      username: attributes.username,\n    };\n  },\n});\n\n/*\nIMPORTANT!\nHere we need to use `qwikLuciaConfig` to correctly configure the `handleRequest` function\n*/\nexport const { handleRequest } = qwikLuciaConfig(lucia);\n\ndeclare module 'lucia' {\n  interface Register {\n    Lucia: typeof lucia;\n    DatabaseUserAttributes: Omit\u003cSelectUser, 'id'\u003e;\n  }\n}\n```\n\n### Set `user` and `session` in SharedMap on every request using `onRequest` handler\n\n```tsx\n// src/routes/layout.tsx\nimport type { RequestHandler } from '@builder.io/qwik-city';\nimport { handleRequest } from '~/server/lucia';\n\n// Run on every request\nexport const onRequest: RequestHandler = async ({ cookie, sharedMap }) =\u003e {\n  const authRequest = handleRequest({ cookie });\n  const { user, session } = await authRequest.validateUser();\n\n  // share the user and session with the rest of the app\n  sharedMap.set('user', user);\n  sharedMap.set('session', session);\n};\n```\n\n### Signup\n\n```tsx\n// src/routes/signup/index.tsx\nimport { handleRequest, lucia } from \"~/lib/lucia\";\n\n// This is just a wrapper around the oslo/password library\nimport { hashPassword } from 'qwik-lucia';\n\nexport const useSignupUser = routeAction$(\n  async (values, { redirect }) =\u003e {\n    try {\n      const passwordHash = await hashPassword(values.password);\n\n      await db.insert(userTable).values({\n        username: values.username,\n        password: passwordHash,\n      });\n    } catch (e) {\n      ... // handle error\n    }\n    // make sure you don't throw inside a try/catch block!\n    throw redirect(303, '/');\n  },\n  // validate the input\n  zod$({\n    username: z.string().min(2),\n    password: z.string().min(5),\n  })\n);\n```\n\n### Login\n\n```tsx\n// src/routes/login/index.tsx\nimport { handleRequest, lucia } from \"~/server/lucia\";\n\n// This is just a wrapper around the oslo/password library\nimport { verifyPassword } from 'qwik-lucia';\n\nexport const useLoginAction = routeAction$(\n  async (values, { cookie, fail }) =\u003e {\n    // Important! Use `handleRequest` to handle the authentication request\n    const authRequest = handleRequest({ cookie });\n\n    try {\n      //1. search for user\n      const [user] = await db\n        .select({\n          id: userTable.id,\n          passwordHash: userTable.password,\n          username: userTable.username,\n        })\n        .from(userTable)\n        .where(eq(userTable.username, values.username));\n\n      //2. if user is not found, throw error\n      if (!user) {\n        return fail(400, {\n          message: 'Incorrect username or password',\n        });\n      }\n\n      // 3. validate password\n      const isValidPassword = await verifyPassword(\n        user.passwordHash,\n        values.password\n      );\n\n      if (!isValidPassword) {\n        return fail(400, {\n          message: 'Incorrect username or password',\n        });\n      }\n\n      // 4. create session\n      const session = await lucia.createSession(user.id, {});\n\n      authRequest.setSession(session); // set session cookie\n    } catch (e) {\n       ... // handle error\n    }\n    // make sure you don't throw inside a try/catch block!\n    throw event.redirect(303, '/');\n  },\n  // validate the input\n  zod$({\n    username: z.string(),\n    password: z.string(),\n  })\n);\n```\n\n### Logout\n\n```tsx\n// src/routes/index.tsx\nimport { handleRequest } from '~/server/lucia';\n\n// Create a user logout action\nexport const useLogoutUserAction = routeAction$(\n  async (values, { cookie, sharedMap, redirect }) =\u003e {\n    const authRequest = handleRequest({ cookie });\n    const session = sharedMap.get('session');\n\n    if (!session) throw redirect(302, '/login');\n\n    // Remove the session from the database and from the cookie - Logout\n    await authRequest.invalidateSessionCookie(session);\n\n    throw redirect(302, '/login');\n  }\n);\n```\n\n### Get User and Session from SharedMap\n\n```tsx\nconst user = sharedMap.get('user');\nconst session = sharedMap.get('session');\n```\n\nExample\n\n```tsx\nexport const isUserLoggedIn = routeLoader$(async ({ sharedMap, redirect }) =\u003e {\n  const user = sharedMap.get('user');\n  const session = sharedMap.get('session');\n\n  if (!user || !session) {\n    throw redirect(302, '/login');\n  }\n\n  return {};\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavocadev%2Fqwik-lucia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgustavocadev%2Fqwik-lucia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavocadev%2Fqwik-lucia/lists"}