{"id":15183823,"url":"https://github.com/puddyclub/firebase-express-template","last_synced_at":"2026-02-25T15:31:54.952Z","repository":{"id":57166716,"uuid":"338065312","full_name":"PuddyClub/Firebase-Express-Template","owner":"PuddyClub","description":"A template for website development using Firebase.","archived":false,"fork":false,"pushed_at":"2022-11-14T05:50:05.000Z","size":86,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-27T23:32:00.967Z","etag":null,"topics":["express","firebase","http-server","nodejs","template"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/PuddyClub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"patreon":"JasminDreasond","ko_fi":"JasminDreasond"}},"created_at":"2021-02-11T15:16:31.000Z","updated_at":"2024-10-01T00:07:33.000Z","dependencies_parsed_at":"2023-01-22T01:45:30.254Z","dependency_job_id":null,"html_url":"https://github.com/PuddyClub/Firebase-Express-Template","commit_stats":null,"previous_names":["tinypudding/firebase-express-template"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PuddyClub/Firebase-Express-Template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PuddyClub%2FFirebase-Express-Template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PuddyClub%2FFirebase-Express-Template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PuddyClub%2FFirebase-Express-Template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PuddyClub%2FFirebase-Express-Template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PuddyClub","download_url":"https://codeload.github.com/PuddyClub/Firebase-Express-Template/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PuddyClub%2FFirebase-Express-Template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281750627,"owners_count":26555294,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-30T02:00:06.501Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["express","firebase","http-server","nodejs","template"],"created_at":"2024-09-27T17:01:35.089Z","updated_at":"2025-10-30T05:33:11.088Z","avatar_url":"https://github.com/PuddyClub.png","language":"JavaScript","funding_links":["https://patreon.com/JasminDreasond","https://ko-fi.com/JasminDreasond","https://www.patreon.com/JasminDreasond","https://ko-fi.com/jasmindreasond"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003cp\u003e\n    \u003ca href=\"https://discord.gg/TgHdvJd\"\u003e\u003cimg src=\"https://img.shields.io/discord/413193536188579841?color=7289da\u0026logo=discord\u0026logoColor=white\" alt=\"Discord server\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/@tinypudding/firebase-express-template\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@tinypudding/firebase-express-template.svg?maxAge=3600\" alt=\"NPM version\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/@tinypudding/firebase-express-template\"\u003e\u003cimg src=\"https://img.shields.io/npm/dt/@tinypudding/firebase-express-template.svg?maxAge=3600\" alt=\"NPM downloads\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.patreon.com/JasminDreasond\"\u003e\u003cimg src=\"https://img.shields.io/badge/donate-patreon-F96854.svg?logo=patreon\" alt=\"Patreon\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://ko-fi.com/jasmindreasond\"\u003e\u003cimg src=\"https://img.shields.io/badge/donate-ko%20fi-29ABE0.svg?logo=ko-fi\" alt=\"Ko-Fi\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\n    \u003ca href=\"https://nodei.co/npm/@tinypudding/firebase-express-template/\"\u003e\u003cimg src=\"https://nodei.co/npm/@tinypudding/firebase-express-template.png?downloads=true\u0026stars=true\" alt=\"npm installnfo\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003c/div\u003e\n\n# Firebase-Express-Template\nA template for website development using Firebase.\n\n\u003c/hr\u003e\n\n## Example\n\n### config.json\nThese are the Firebase Server settings for the @tinypudding/firebase-lib module and the domain validator from the @tinypudding/puddy-lib.\n```json\n{\n    \"options\": {\n        \"id\": \"main\"\n    },\n    \"firebase\": {\n        \"databaseURL\": \"example\",\n        \"authDomain\": \"example.com\",\n        \"serviceAccountId\": \"example@example.iam.gserviceaccount.com\",\n    },\n    \"domain\": \"example.com\"\n}\n```\n\n### firebase_web.json\nThese are the Firebase Client settings that are in your website.\n```json\n{\n    \"apiKey\": \"\",\n    \"authDomain\": \"example.com\",\n    \"projectId\": \"example\",\n    \"appId\": \"\"\n}\n```\n\n### index.js\n```js\n// Prepare Modules\nconst functions = require('firebase-functions');\nconst tinyCfg = require('./config.json');\nconst expressTemplate = require('@tinypudding/firebase-express-template');\n\n// Get a Custom Firebase Cert\nconst isEmulator = require('@tinypudding/firebase-lib/isEmulator');\nif(isEmulator()){\n    const admin = require('firebase-admin');\n    tinyCfg.firebase.credential = admin.credential.cert(require('./firebase.json'));\n}\n\n// Prepare App\nconst app = expressTemplate({\n\n    // File Config\n    fileCfg: {\n        fileMaxAge: '2592000000'\n    },\n\n    // Error Page\n    errorPage: (req, res, data, cfg, firebaseWeb) =\u003e {\n\n        // Is a Error Page\n        if (res \u0026\u0026 req) {\n\n            // Logger\n            const logger = require('@tinypudding/firebase-lib/logger');\n\n            // Prepare Result\n            const result = { code: data.code };\n\n            // Get Error Message\n            if (data.message) { result.text = data.message; }\n            else if (data.err \u0026\u0026 data.err.message) { result.text = data.err.message; }\n            else { result.text = '???'; }\n\n            // Log\n            if (data.code !== 404) {\n                let errorData = null;\n                if (data.err) { errorData = data.err; }\n                else if (data.message) { errorData = new Error(data.message); }\n                else { errorData = new Error('Unknown Error'); }\n                errorData.code = data.code;\n                logger.error(errorData);\n            }\n\n            // Send Error Page\n            return res.json(result);\n\n        } \n        \n        // Nothing\n        else { return; }\n\n    },\n\n    // Website Middleware\n    middleware: function (web) {\n     \n        // Nunjucks Module. You can use any module here.\n        const path = require('path');\n        const nunjucks = require('nunjucks');\n        nunjucks.configure(path.join(__dirname, '../views'), {\n            autoescape: true,\n            express: web.app\n        });\n\n        web.app.set('view engine', 'nunjucks');\n\n        // Homepage (web.dsSession will install the Discord Session in this page)\n        web.app.get('/', web.dsSession(), (req, res) =\u003e {\n            console.log(req.discord_session);\n            res.render('test');\n            return;\n        });\n\n        // Install Firebase Google oAuth in this page\n        web.app.get('/firebasePage', web.googleFireAuth, (req, res) =\u003e {\n            console.log(req.firebase_session);\n            res.render('test');\n            return;\n        });\n\n        // Complete\n        return web.fn();\n     \n    },\n    \n    // config.json\n    cfg: tinyCfg,\n\n    // Helmet\n    // https://www.npmjs.com/package/helmet\n    helmet: {\n        contentSecurityPolicy: {\n            directives: {\n                defaultSrc: [\"'self'\", \"'unsafe-inline'\", 'https://securetoken.googleapis.com/', 'https://www.googleapis.com/']\n            }\n        }\n    },\n\n    // Main\n    main: {\n        domainValidator: {\n\n            // Domain Validator\n            domain: tinyCfg.domain, \n\n            // Static Path Protector\n            staticPath: ['/css/', '/img/', '/js/', '/sound/', '/webfonts/'] \n\n        }\n    },\n\n    // Firebase\n    firebase: { options: tinyCfg.options, firebase: tinyCfg.firebase },\n    firebaseWeb: require('./firebase_web.json'),\n\n    // Cookie Session Module Settings\n    // https://www.npmjs.com/package/cookie-session\n    cookieSession: {\n        keys: [\n            \"FkWS8HFZUt\",\n            \"1EC4RdpUEQ\"\n        ]\n    },\n\n    // csrftoken\n    // https://www.npmjs.com/package/@tinypudding/csrftoken-lib\n    csrftoken: {\n\n        // This is the path of the module method ( csrftoken(csrfToken', 1, 'hours'); )\n        module: ['csrfToken', 1, 'hours'],\n\n        // The Callback of the Csrf Token validator for all other modules of the template.\n        callback: function (req) {\n        \n            // Prepare Result\n            const result = { now: null, server: null };\n\n            // Get Body\n            if(req.body \u0026\u0026 typeof req.body.csrftoken === \"string\") { result.now = req.body.csrftoken; }\n\n            // Get Server\n            if(req.csrfToken \u0026\u0026 req.csrfToken.now \u0026\u0026 typeof req.csrfToken.now.value === \"string\") { result.server = req.csrfToken.now.value; }\n\n            // Send Reuslt\n            return result; \n        \n        }\n\n    },\n\n    // Timezone Module (You need the module cookie-session installed)\n    // https://www.npmjs.com/package/@tinypudding/timezone-cookie-session\n    timezone: {\n        urls: { setTime: '/setTime' },\n        clock24: true,\n        autoList: true,\n        setSecondary: true,\n        fileMaxAge: '2592000000'\n    },\n\n    // i18 Module  (You need the module cookie-session installed)\n    // https://www.npmjs.com/package/@tinypudding/i18\n    i18: {\n\n        // Vars Session Names.\n        cfg: {\n\n            // Vars cookie-session.\n            varsSession: {\n                sessionLang: 'sessionLang',\n                userLang: 'userLang',\n                nowLang: 'nowLang',\n                langIsUser: 'langIsUser'\n            },\n\n            // Lang List.\n            list: [\n                { value: 'en', name: 'English' },\n                { value: 'pt-br', name: 'Português Brasil' }\n            ]\n\n        },\n\n        // Return true or false if your web session is a logged user.\n        getIsUser: function(req, res) {\n\n            // Set the user session boolean to false\n            return false;\n\n        },\n\n        // Get CSRF Token\n        getCsrfToken: function (req, res) {\n            return new Promise(function (resolve) {\n\n                // Return csrfToken\n                resolve({\n                    now: '', // CSRF Token sent by the user\n                    server: '' // Server CSRF Token\n                });\n\n                // Complete\n                return;\n\n            });\n        },\n\n        // URLs of the module.\n        urls: {\n            setLang: '/setLang'\n        },\n\n    },\n\n    /* \n    \n        Discord OAuth2 (You need the module cookie-session installed)\n\n        If you insert a bot token and have Discord.JS (https://discord.js.org/) installed, req.discord_session.bot will return a Discord.JS Client. \n        \n        Do not forget that this Discord.JS Client is not connected to webSockets so as not to allow your Firebase application to be trying to make various Websocket connections with each request on your website.\n\n        To start Discord.JS in your application you need to call the method req.discord_session.bot().\n        When this method is called, it will transform req.discord_session.bot into a Discord.JS Client.\n        If the Discord.JS module is not detected, it will return the module's default methods in the req.discord_session.bot.\n\n        https://www.npmjs.com/package/@tinypudding/discord-oauth2\n    \n    */\n    discordOAuth2: {\n\n        // Database to get the bot data\n        database: {\n            \n            // Bot Path\n            botPath: 'bots',\n\n            // App Path\n            appPath: 'apps',\n\n            // Database Name\n            name: 'tiny-boop',\n            \n            // Paths that are authorized to read the database to obtain the Auth without needing the user logged on. You can use the value \"*\" to allow the entire website.\n            pathNoUser: [],\n        \n        },\n\n        // Localhost to test\n        localhost: 'localhost:5000',\n\n        // Base\n        discord: {\n\n            // Discord URL\n            url: {\n                commandLogin: '/commandLogin',\n                botLogin: '/botLogin',\n                login: '/login',\n                logout: '/logout',\n                redirect: '/redirect',\n                firebaseLogin: '/firebase/login',\n                firebaseLogout: '/firebase/logout'\n            },\n\n            // Auth. If you don't set any database values to get the values automatically, the values written here will be used. You must at least enter the discordScope. \n            auth: {\n                bot_token: '',\n                client_id: '',\n                client_secret: '',\n                discordScope: ['identify', 'email'],\n                first_get_user: true\n            },\n\n            // Crypto Key\n            crypto: { key: 'tinypudding123456789012345678900' },\n\n            // Check Auth Time\n            checkAuthTime: (decodedIdToken) =\u003e {\n\n                // Only process if the user just signed in in the last 5 minutes.\n                if (new Date().getTime() / 1000 - decodedIdToken.auth_time \u003c 5 * 60) {\n                    return true;\n                }\n\n                // Nope\n                else { return false; }\n\n            },\n\n            // Cookie Time Generator\n            cookieTimeGenerator: (decodedIdToken) =\u003e {\n\n                // Set session expiration to 5 days.\n                const expiresIn = 60 * 60 * 24 * 5 * 1000;\n\n                // Complete\n                return expiresIn;\n\n            },\n\n            // Configuration\n            cfg: {\n\n                // Need Email Verification to login in \n                needEmailVerified: true,\n\n                // Firebase Login Redirect\n                redirect: {\n\n                    /* Login */\n                    login: function (data, req, res, firebaseCfg, webCfg) {\n\n                        // res.render is a Render Module from Nunjucks\n                        return res.render('firebase_redirect/login', {\n\n                            // the Firebase Web Config to insert in the page.\n                            firebase_cfg: JSON.stringify(firebaseCfg),\n\n                            // The main function string to be send to login page.\n                            start_login: data.functions.run,\n\n                            // The Firebase token to do the login.\n                            token: data.token,\n\n                            // The Csrf Token\n                            key: data.key,\n\n                            // The Final Redirect URL\n                            redirect_url: data.redirect\n                            \n                        });\n\n                    },\n\n                    /* Logout */\n                    logout: function (data, req, res, firebaseCfg, webCfg) {\n\n                        // res.render is a Render Module from Nunjucks\n                        return res.render('firebase_redirect/logout', {\n\n                            // the Firebase Web Config to insert in the page.\n                            firebase_cfg: JSON.stringify(firebaseCfg),\n\n                            // The main function string to be send to logout page.\n                            start_logout: data.functions.run,\n\n                            // The Firebase token to do the login.\n                            token: data.token,\n\n                            // The Csrf Token\n                            key: data.key,\n\n                            // Firebase Key\n                            original_key: data.original_key,\n\n                            // The Final Redirect URL\n                            redirect_url: data.redirect\n\n                        });\n\n                    },\n\n                    /* Webhook Discord Creator Callback */\n                    webhook: function (data, req, res) { return res.send(''); }\n\n                }\n\n            },\n\n        }\n\n    }\n\n});\n\n// Website Function\nexports.example = functions.https.onRequest(app);\n```\n\n\u003c/hr\u003e\n\n## Firebase Google oAuth\nThis script was developed specifically to work with Google's Auth of Firebase.\n\nFirst you need to configure your JSON data and your custom method file if you want to add anything extra to happen during the login.\n\n### JSON Data \n```js\nconst JSONDATA = {\n\n    // Vars Session\n    varsSession: {\n        firebase_token: \"firebase_token\",\n        google_token: \"google_token\"\n    },\n\n    // URL\n    url: {\n        nativeLogin: \"/firebase/nativeLogin.js\",\n        nativeLoginClient: \"/firebase/nativeLoginClient.js\",\n        nativeLogout: \"/firebase/nativeLogout.js\",\n        loginServer: \"/firebase/loginServer\",\n        logoutServer: \"/firebase/logoutServer\",\n        fireLogin: \"/fireLogin\"\n    },\n\n    // Login Redirect Meta\n    redirectMetaPages: {\n        \n        // Basic Info\n        login: \"\u003cscript src=\\\"/file.js\\\"\u003e\u003c/script\u003e\",\n        loginTitle: \"Login...\",\n        firebaseVersion: \"8.2.6\",\n\n        // Check Auth Time\n        checkAuthTime: (decodedIdToken) =\u003e {\n\n            // Only process if the user just signed in in the last 5 minutes.\n            if (new Date().getTime() / 1000 - decodedIdToken.auth_time \u003c 5 * 60) {\n                return true;\n            }\n\n            // Nope\n            else { return false; }\n\n        },\n\n        // Cookie Time Generator\n        cookieTimeGenerator: (decodedIdToken) =\u003e {\n\n            // Set session expiration to 5 days.\n            const expiresIn = 60 * 60 * 24 * 5 * 1000;\n\n            // Complete\n            return expiresIn;\n\n        }\n        \n    }\n\n}\n\n// Start App\nconst app = expressTemplate({\n\n    ...\n\n    // Insert the JSON Data here\n    firebaseGoogle: JSONDATA\n\n    ...\n\n});\n```\n\n### /file.js\n```js\nvar customFirebaseLoginRedirect = {\n\n    // Before Login\n    beforeLogin: (provider, type, extra) =\u003e {\n        // provider - firebase.auth.GoogleAuthProvider() value\n        // type - event type \n        // extra - some extra value\n        return;\n    },\n\n    // Before Logout\n    beforeLogout: () =\u003e {\n        return;\n    },\n\n    // Fail Login\n    failLogout: () =\u003e {\n        return;\n    },\n\n    // Error\n    failLogout: (err, id) =\u003e {\n        alert(err.message);\n        return;\n    }\n\n};\n```\n\n### /index.html (meta)\nNow you need to add META to your page.\n\n```html\n\u003cscript\u003efirebase.initializeApp(firebaseCfg);\u003c/script\u003e\n\u003cscript src=\"/firebase/nativeLoginClient.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"/firebase/nativeLogout.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"/file.js\"\u003e\u003c/script\u003e\n```\n\nThe file \"nativeLoginClient.js\" contains the method \"updateFirebaseUserToken();\".\nYou can use this method to validate that your server token is valid. \nYou can choose a custom method to run after the new token is updated.\nThe default method is made to reload the page.\n\n```js\nvar user_token_validated_in_the_server_side = false;\nfirebase.auth().onAuthStateChanged(function (user) {\n\n    // The Value is False. The new token will be added now.\n    if(user \u0026\u0026 !user_token_validated_in_the_server_side) {\n        updateFirebaseUserToken(user, (json) =\u003e {\n\n            // Show Request Result\n            console.log(json); \n            \n            // Reload the page\n            location.reload(); \n            \n        });\n    }\n\n});\n```\n\n### /index.html (body)\nDon't forget to add the login and logout buttons.\n\n```html\n\u003c!-- Logout Button --\u003e\n\u003ca id=\"logout\" href=\"javascript:void(0);\"\u003e\n    Logout\n\u003c/a\u003e\n\u003cscript\u003e$(\"#logout\").click(function () { tinyLogoutFirebase(); });\u003c/script\u003e\n\n\u003c!-- Login Button --\u003e\n\u003ca href=\"/fireLogin?redirect=homepage\"\u003e \u003c!-- This url will redirect to /homepage --\u003e\n    Login\n\u003c/a\u003e\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpuddyclub%2Ffirebase-express-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpuddyclub%2Ffirebase-express-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpuddyclub%2Ffirebase-express-template/lists"}