├── .envrc ├── .gitignore ├── .node-version ├── LICENSE.txt ├── README.md ├── package-lock.json ├── package.json ├── public └── index.html ├── src ├── app.ts ├── index.ts └── init.ts ├── tsconfig.json ├── webpack.config.base.js ├── webpack.config.dev.js └── webpack.config.prod.js /.envrc: -------------------------------------------------------------------------------- 1 | dotenv 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .env 4 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 14.15.4 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019-2021 Classmethod, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # liff-app-template 2 | 3 | ## Getting Started 4 | 5 | Select `Use this template` button and create a repo for your new project. 6 | Then, clone the repo to your local workspace. 7 | 8 | ### Making LIFF App 9 | 10 | Set `https://localhost:9443/` to endpoint URL. 11 | 12 | refer: https://developers.line.biz/ja/docs/liff/registering-liff-apps/ 13 | 14 | ### Making `.env` file 15 | 16 | `.env` file includes LIFF ID is needed to run this app. 17 | 18 | ```console 19 | echo LIFF_ID=xxxxxxxxxx-yyyyyyyy > .env 20 | ``` 21 | 22 | ### Starting Dev Server 23 | 24 | Run following commands to start dev server. 25 | 26 | ```console 27 | npm install 28 | npm start 29 | ``` 30 | 31 | Access `https://localhost:9443/` on your browser. 32 | 33 | In Google Chrome, if you saw the warning like "Your connection is not private" `NET::ERR_CERT_AUTHORITY_INVALID`, click `Advanced` then click `Proceed to localhost(unsafe)`. You may set `Enabled` to "Allow invalid certificates for resources loaded from localhost" on `chrome:flags` page. 34 | 35 | In Firefox, if you saw the warning like "Warning: Potential Security Risk Ahead", click `Advanced...` then click `Accept the Risk and Continue` 36 | 37 | ## Building 38 | 39 | ```console 40 | npm run build 41 | ``` 42 | 43 | Generates bundled codes in the dir `/dist`. 44 | 45 | ## Deployments 46 | 47 | Build and deploy files in `/dist` to your favorite file hosting service. 48 | 49 | ## Licenses 50 | 51 | Apache License 2.0 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "liff-app-template", 3 | "version": "1.0.2", 4 | "author": "Classmethod, Inc.", 5 | "license": "Apache-2.0", 6 | "licenses": { 7 | "type": "Apache-2.0", 8 | "url": "http://www.apache.org/licenses/LICENSE-2.0" 9 | }, 10 | "scripts": { 11 | "start": "webpack serve --config webpack.config.dev.js", 12 | "build": "webpack --config webpack.config.prod.js", 13 | "type-check": "tsc --noEmit" 14 | }, 15 | "devDependencies": { 16 | "clean-webpack-plugin": "3.0.0", 17 | "dotenv-webpack": "6.0.2", 18 | "html-webpack-plugin": "5.2.0", 19 | "typescript": "4.2.2", 20 | "webpack": "5.24.2", 21 | "webpack-cli": "4.5.0", 22 | "webpack-dev-server": "3.11.2", 23 | "webpack-merge": "5.7.3" 24 | }, 25 | "dependencies": { 26 | "@line/liff": "2.2.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |${error}` 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import App from './app' 2 | 3 | App() 4 | -------------------------------------------------------------------------------- /src/init.ts: -------------------------------------------------------------------------------- 1 | import liff from '@line/liff' 2 | 3 | export default function init() { 4 | const LIFF_ID = process.env.LIFF_ID 5 | if (LIFF_ID === undefined) { 6 | throw new Error('Set LIFF ID as env var "LIFF_ID"') 7 | } 8 | 9 | return new Promise(async (resolve, reject) => { 10 | try { 11 | await liff.init({ 12 | liffId: LIFF_ID 13 | }) 14 | if (!liff.isLoggedIn()) { 15 | liff.login() 16 | } 17 | 18 | resolve('') 19 | } 20 | catch(error) { 21 | reject(error) 22 | } 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "charset": "utf8", 4 | "newLine": "LF", 5 | "target": "ESNext", 6 | "module": "CommonJS", 7 | "lib": ["DOM", "ESNext"], 8 | "jsx": "preserve", 9 | "rootDir": "./src", 10 | "outDir": "./dist", 11 | "esModuleInterop": true, 12 | "declaration": true, 13 | "removeComments": true, 14 | "resolveJsonModule": true, 15 | "strict": true, 16 | "noErrorTruncation": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitReturns": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "typeRoots": ["./node_modules/@types", "./src/@types"] 23 | }, 24 | "exclude": ["node_modules", "dist"] 25 | } 26 | -------------------------------------------------------------------------------- /webpack.config.base.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { CleanWebpackPlugin } = require('clean-webpack-plugin') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | const DotEnv = require('dotenv-webpack') 5 | 6 | module.exports = { 7 | entry: './src/index.ts', 8 | output: { 9 | path: path.resolve(__dirname, 'dist'), 10 | filename: '[name].[contenthash].js', 11 | }, 12 | resolve: { 13 | extensions: ['.ts'] 14 | }, 15 | plugins: [ 16 | new CleanWebpackPlugin(), 17 | new HtmlWebpackPlugin({ 18 | inject: true, 19 | template: 'public/index.html' 20 | }), 21 | new DotEnv(), 22 | ], 23 | } 24 | -------------------------------------------------------------------------------- /webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge') 2 | const baseConfig = require('./webpack.config.base.js') 3 | 4 | const config = merge(baseConfig, { 5 | mode: 'development', 6 | devtool: 'inline-source-map', 7 | devServer: { 8 | https: true, 9 | contentBase: './dist', 10 | port: 9443, 11 | }, 12 | resolve: { 13 | extensions: ['.ts', '.js'] 14 | }, 15 | }) 16 | 17 | module.exports = config 18 | -------------------------------------------------------------------------------- /webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge') 2 | const baseConfig = require('./webpack.config.base.js') 3 | 4 | module.exports = merge(baseConfig, { 5 | mode: 'production', 6 | }) 7 | --------------------------------------------------------------------------------