├── .env.example ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── README.md ├── guides └── laravel-sanctum.md ├── package-lock.json ├── package.json ├── playwright.config.ts ├── postcss.config.cjs ├── run ├── src ├── app.css ├── app.d.ts ├── app.html ├── hooks │ ├── laravel-sanctum-fake-logged-in.ts │ ├── laravel-sanctum-fake-logged-out.ts │ ├── laravel-sanctum.ts │ └── sveltekit-default.ts ├── lib │ ├── Counter.svelte │ ├── components │ │ ├── Accordion.svelte │ │ ├── AccordionItem.svelte │ │ ├── Alert.svelte │ │ ├── Badge.svelte │ │ ├── Breadcrumb.svelte │ │ ├── ButtonGroup.svelte │ │ ├── Buttons.svelte │ │ ├── Card.svelte │ │ ├── Carousel.svelte │ │ ├── CloseButton.svelte │ │ ├── Code.svelte │ │ ├── Collapse.svelte │ │ ├── Docs │ │ │ ├── DocAccordion.svelte │ │ │ ├── DocAlert.svelte │ │ │ └── DocBadge.svelte │ │ ├── Dropdowns.svelte │ │ ├── ListGroup.svelte │ │ ├── Modal.svelte │ │ ├── NavsAndTabs.svelte │ │ ├── Pagination.svelte │ │ ├── Popovers.svelte │ │ ├── Spinners.svelte │ │ ├── Toasts.svelte │ │ └── Tooltips.svelte │ ├── form.ts │ ├── header │ │ ├── Header.svelte │ │ └── svelte-logo.svg │ ├── images │ │ ├── github.svg │ │ ├── svelte-logo.svg │ │ ├── svelte-welcome.png │ │ └── svelte-welcome.webp │ ├── ioevents │ │ ├── click.ts │ │ └── keydown.ts │ ├── tailwind.css │ ├── templates │ │ ├── Admin │ │ │ ├── API │ │ │ │ └── form.ts │ │ │ ├── Config │ │ │ │ └── charts.ts │ │ │ ├── Header.svelte │ │ │ ├── Images │ │ │ │ ├── create-account-office-dark.jpeg │ │ │ │ ├── create-account-office.jpeg │ │ │ │ ├── dashboard.png │ │ │ │ ├── forgot-password-office-dark.jpeg │ │ │ │ ├── forgot-password-office.jpeg │ │ │ │ ├── github.svg │ │ │ │ ├── login-office-dark.jpeg │ │ │ │ ├── login-office.jpeg │ │ │ │ └── twitter.svg │ │ │ ├── SideBar.svelte │ │ │ └── ToggleTheme.svelte │ │ └── Blog │ │ │ ├── Config │ │ │ ├── links.json │ │ │ └── particle.json │ │ │ ├── Header.svelte │ │ │ ├── Images │ │ │ ├── company1.png │ │ │ ├── company2.svg │ │ │ ├── company3.png │ │ │ └── company4.jpeg │ │ │ ├── Particles │ │ │ ├── Particles.svelte │ │ │ ├── global.d.ts │ │ │ ├── index.d.ts │ │ │ └── index.ts │ │ │ └── SideBar.svelte │ └── translator.ts ├── routes │ ├── admin │ │ ├── (authenticated) │ │ │ ├── +layout.svelte │ │ │ ├── +page.svelte │ │ │ ├── buttons │ │ │ │ └── +page.svelte │ │ │ ├── cards │ │ │ │ └── +page.svelte │ │ │ ├── charts │ │ │ │ └── +page.svelte │ │ │ ├── components │ │ │ │ └── +page.svelte │ │ │ ├── forms │ │ │ │ └── +page.svelte │ │ │ ├── modals │ │ │ │ └── +page.svelte │ │ │ └── tables │ │ │ │ └── +page.svelte │ │ ├── (guest) │ │ │ ├── +layout.svelte │ │ │ ├── auth │ │ │ │ ├── login │ │ │ │ │ ├── +page.server.ts │ │ │ │ │ └── +page.svelte │ │ │ │ └── logout │ │ │ │ │ └── +page.server.ts │ │ │ ├── forgot-password │ │ │ │ └── +page.svelte │ │ │ └── register │ │ │ │ └── +page.svelte │ │ ├── +error.svelte │ │ ├── +layout.server.ts │ │ └── html_head.svelte │ ├── api.ts │ ├── blog │ │ ├── +layout.svelte │ │ ├── +page.svelte │ │ └── resume │ │ │ └── +page.svelte │ └── demo │ │ ├── +layout.svelte │ │ ├── +page.svelte │ │ ├── +page.ts │ │ ├── Counter.svelte │ │ ├── Header.svelte │ │ ├── about │ │ ├── +page.svelte │ │ └── +page.ts │ │ ├── styles.css │ │ └── sverdle │ │ ├── +page.server.ts │ │ ├── +page.svelte │ │ ├── game.test.ts │ │ ├── game.ts │ │ ├── how-to-play │ │ ├── +page.svelte │ │ └── +page.ts │ │ ├── reduced-motion.ts │ │ └── words.server.ts ├── service-worker.ts └── stores │ └── menus.ts ├── start ├── route.js ├── tailwind │ ├── admin.cjs │ ├── daisy-ui.cjs │ └── index.cjs └── vite │ ├── default.vite.config.js │ └── index.js ├── static ├── favicon.png ├── icons │ ├── icon-128x128.png │ ├── icon-144x144.png │ ├── icon-152x152.png │ ├── icon-192x192.png │ ├── icon-384x384.png │ ├── icon-48x48.png │ ├── icon-512x512.png │ ├── icon-72x72.png │ └── icon-96x96.png ├── manifest.json ├── robots.txt ├── svelte-welcome.png └── svelte-welcome.webp ├── svelte.config.js ├── tailwind.config.cjs ├── tests └── demo.ts ├── tsconfig.json └── vite.config.js /.env.example: -------------------------------------------------------------------------------- 1 | VITE_APP_NAME="Project Name" 2 | VITE_BASE_API="http://api.local" 3 | VITE_SESSION_NAME="laravel_session" 4 | 5 | # url path 6 | VITE_LOGIN_PATH="/auth/login" 7 | VITE_LOGOUT_PATH="/auth/logout" 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript'), 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020, 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .DS_Store 3 | node_modules 4 | /build 5 | /.svelte-kit 6 | /package 7 | .env 8 | .env.* 9 | !.env.example 10 | .vercel 11 | .output 12 | /functions 13 | /.vercel_build_output 14 | /.idea 15 | /vite.config.js.timestamp* 16 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v16.14.2 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "pluginSearchDirs": ["."], 7 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }], 8 | "semi": false 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SvelteKit Projects 2 | 3 | - [./run and src/route.js](#run-and-srcroutejs) 4 | - [Playwright Test Cases](#playwright-test-cases) 5 | - [Demo](#demo) 6 | - [Framework Specific Guidelines](#framework-specific-guidelines) 7 | - [Disclaimer](#disclaimer) 8 | 9 | The copy of this branch should have at least the `v1.15.10` of `@sveltejs/kit` 10 | 11 | ## ./run and src/route.js 12 | 13 | Dynamic way of serving the `./src/routes/admin`, we've added a condition inside our `start/route.js` to pre-determine the folder we want. 14 | 15 | ```bash 16 | # this demonstrates a fake logged in 17 | $> ./run admin dev 18 | $> ./run admin-in dev 19 | 20 | # this demonstrates a fake logged out 21 | $> ./run admin-out dev 22 | 23 | # this connects to your laravel sanctum 24 | $> ./run admin-laravel-sanctum dev 25 | ``` 26 | 27 | The above command is similar to what it looks like below 28 | 29 | ```bash 30 | $> ROUTE_FOLDER=admin npm run dev 31 | ``` 32 | 33 | We've stored more route projects, such as the original `demo` of sveltekit and my own resumé `blog` 34 | 35 | ```bash 36 | # this demonstrates my bio and resumé 37 | $> ./run blog dev 38 | 39 | # this demonstrates the original sveltekit counter + todo 40 | $> ./run demo dev 41 | ``` 42 | 43 | ## Playwright Test Cases 44 | 45 | When writing a test cases, rule of thumb is to name your tests with/by specific words, such as **"demo:"** 46 | 47 | ```js 48 | // tests/demo.js 49 | test('demo: about page has expected h1', async ({ page }) => { 50 | // ... 51 | }); 52 | ``` 53 | 54 | Then you can run specific folders by executing it this way 55 | 56 | ```bash 57 | ./run demo test -- -g "demo:" 58 | ``` 59 | 60 | ## Demo 61 | 62 | - [Admin logged-in](https://sveltekit-windmill-admin.vercel.app/) 63 | - [Admin logged-out](https://sveltekit-windmill-admin-out.vercel.app/) 64 | - [Bio / Resumé](https://daison.vercel.app/) 65 | 66 | ## Framework Specific Guidelines 67 | 68 | - [Setup Laravel Sanctum](/guides/laravel-sanctum.md) 69 | - ***You have backend framework? Add your sveltekit guidelines here!*** 70 | 71 | ## Disclaimer 72 | 73 | - (Admin UI) Most of the design was based originally from [Estevan Maito's](https://github.com/estevanmaito/windmill-dashboard) 74 | 75 | ## Project Sponsors 76 | 77 | - https://formatterjson.com/ 78 | - https://jsonlinter.com/ 79 | -------------------------------------------------------------------------------- /guides/laravel-sanctum.md: -------------------------------------------------------------------------------- 1 | # SvelteKit + Laravel Sanctum Setup 2 | 3 | Install sanctum under your laravel 4 | 5 | ```bash 6 | laravel/ :~$ composer require laravel/sanctum 7 | ``` 8 | 9 | Add a new route group under your `app/Http/Kernel.php` 10 | 11 | ```php 12 | 'api' => [ 13 | \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 14 | 'throttle:api', 15 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 16 | ], 17 | ``` 18 | 19 | Under `routes/api.php` 20 | 21 | ```php 22 | Route::middleware('auth:sanctum')->group(['middleware' => 'auth:sanctum'], function () { 23 | Route::post('/login', function (Request $request) { 24 | $credentials = $request->validate([ 25 | 'email' => ['required', 'email'], 26 | 'password' => ['required'], 27 | ]); 28 | 29 | return response()->json(['authenticated' => Auth::attempt($credentials)]); 30 | }); 31 | 32 | Route::get('/logged-in', function (Request $request) { 33 | return response()->json([ 34 | 'user' => $request->user()->only('id', 'email', 'first_name', 'last_name', 'image'), 35 | ]); 36 | }); 37 | 38 | Route::match(['get', 'post'], '/logout', function (Request $request) { 39 | \Illuminate\Support\Facades\Auth::logout(); 40 | return response()->json(['authenticated' => false]); 41 | }); 42 | }); 43 | ``` 44 | 45 | The above code, we serve 3 routes, that is `/login`, `/logged-in` and `/logout` 46 | 47 | ## SvelteKit Starter Configuration 48 | 49 | Update the `hooks` inside **svelte.config.js** 50 | 51 | ```diff 52 | - hooks: `src/hooks/laravel-sanctum-fake-logged-in.ts`, 53 | + hooks: `src/hooks/laravel-sanctum.ts`, 54 | ``` 55 | 56 | Copy `.env.example` and make it `.env` 57 | 58 | ```bash 59 | sveltekit-starter/ :~$ cp .env.example .env 60 | ``` 61 | 62 | Then update the `VITE_BASE_API` based on your laravel url. 63 | 64 | ### How the hooks work? 65 | 66 | To explain about `laravel-sanctum.js` file 67 | 68 | - it will check if there are `locals.user` loaded, or else it fetches to your laravel endpoint `/logged-in` and passing the **user** object inside **locals.user** 69 | - then, if `laravel_session` does not exists, it will fetch `/sanctum/csrf-cookie` and sets the cookie 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sveltekit-starter", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "dev": "vite dev", 6 | "build": "vite build", 7 | "preview": "vite preview", 8 | "test": "playwright test", 9 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 11 | "test:unit": "vitest", 12 | "lint": "prettier --plugin-search-dir . --check . && eslint .", 13 | "format": "prettier --plugin-search-dir . --write ." 14 | }, 15 | "devDependencies": { 16 | "@fontsource/fira-mono": "^4.5.10", 17 | "@neoconfetti/svelte": "^1.0.0", 18 | "@playwright/test": "^1.28.1", 19 | "@sveltejs/adapter-auto": "^2.0.0", 20 | "@sveltejs/kit": "^1.5.0", 21 | "@types/cookie": "^0.5.1", 22 | "@typescript-eslint/eslint-plugin": "^5.45.0", 23 | "@typescript-eslint/parser": "^5.45.0", 24 | "eslint": "^8.28.0", 25 | "eslint-config-prettier": "^8.5.0", 26 | "eslint-plugin-svelte": "^2.26.0", 27 | "prettier": "^2.8.0", 28 | "prettier-plugin-svelte": "^2.8.1", 29 | "svelte": "^3.54.0", 30 | "svelte-check": "^3.0.1", 31 | "tslib": "^2.4.1", 32 | "typescript": "^5.0.0", 33 | "vite": "^4.3.0", 34 | "vitest": "^0.25.3", 35 | "@sveltejs/adapter-vercel": "^1.0.0-next.62", 36 | "autoprefixer": "^10.2.5", 37 | "postcss": "^8.2.15", 38 | "svelte-bootstrap-icons": "^1.8.0", 39 | "tailwindcss": "^3.1.8", 40 | "tsparticles": "^2.2.4", 41 | "@esbuild-plugins/node-globals-polyfill": "^0.1.1", 42 | "@esbuild-plugins/node-modules-polyfill": "^0.1.4", 43 | "@lukeed/uuid": "^2.0.0", 44 | "@tailwindcss/typography": "^0.5.7", 45 | "browserify-zlib": "^0.2.0", 46 | "buffer": "^6.0.3", 47 | "cookie": "^0.4.1", 48 | "daisyui": "^2.27.0", 49 | "events": "^3.3.0", 50 | "leaflet": "^1.9.2", 51 | "process": "^0.11.10", 52 | "stream": "^0.0.2", 53 | "stream-browserify": "^3.0.0", 54 | "svelte-chartjs": "^1.0.1", 55 | "svelte-particles": "^2.2.4", 56 | "util": "^0.12.4" 57 | }, 58 | "type": "module" 59 | } 60 | -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import type { PlaywrightTestConfig } from '@playwright/test'; 2 | 3 | const config: PlaywrightTestConfig = { 4 | webServer: { 5 | command: 'npm run build && npm run preview', 6 | port: 4173 7 | }, 8 | testDir: 'tests', 9 | testMatch: /(.+\.)?(test|spec)\.[jt]s/ 10 | }; 11 | 12 | export default config; 13 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [require('tailwindcss'), require('autoprefixer')] 3 | } 4 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # How to? 3 | # ./run {route-folder} {packages.scripts} 4 | # 5 | # As an example below: 6 | # ./run demo dev 7 | # ./run admin dev 8 | # ./run admin-in dev 9 | # ./run admin-out dev 10 | # ./run blog dev 11 | # ./run landing dev 12 | # 13 | # Others such as: 14 | # ./run admin build 15 | # ./run admin package 16 | ROUTE_FOLDER=$1 $(which npm) run $2 ${@:3} 17 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | @import '@fontsource/fira-mono'; 2 | 3 | :root { 4 | font-family: Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 5 | Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 6 | --font-mono: 'Fira Mono', monospace; 7 | --pure-white: #ffffff; 8 | --primary-color: #b9c6d2; 9 | --secondary-color: #d0dde9; 10 | --tertiary-color: #edf0f8; 11 | --accent-color: #ff3e00; 12 | --heading-color: rgba(0, 0, 0, 0.7); 13 | --text-color: #444444; 14 | --background-without-opacity: rgba(255, 255, 255, 0.7); 15 | --column-width: 42rem; 16 | --column-margin-top: 4rem; 17 | } 18 | 19 | body { 20 | min-height: 100vh; 21 | margin: 0; 22 | background-color: var(--primary-color); 23 | background: linear-gradient( 24 | 180deg, 25 | var(--primary-color) 0%, 26 | var(--secondary-color) 10.45%, 27 | var(--tertiary-color) 41.35% 28 | ); 29 | } 30 | 31 | body::before { 32 | content: ''; 33 | width: 80vw; 34 | height: 100vh; 35 | position: absolute; 36 | top: 0; 37 | left: 10vw; 38 | z-index: -1; 39 | background: radial-gradient( 40 | 50% 50% at 50% 50%, 41 | var(--pure-white) 0%, 42 | rgba(255, 255, 255, 0) 100% 43 | ); 44 | opacity: 0.05; 45 | } 46 | 47 | #svelte { 48 | min-height: 100vh; 49 | display: flex; 50 | flex-direction: column; 51 | } 52 | 53 | h1, 54 | h2, 55 | p { 56 | font-weight: 400; 57 | color: var(--heading-color); 58 | } 59 | 60 | p { 61 | line-height: 1.5; 62 | } 63 | 64 | a { 65 | color: var(--accent-color); 66 | text-decoration: none; 67 | } 68 | 69 | a:hover { 70 | text-decoration: underline; 71 | } 72 | 73 | h1 { 74 | font-size: 2rem; 75 | text-align: center; 76 | } 77 | 78 | h2 { 79 | font-size: 1rem; 80 | } 81 | 82 | pre { 83 | font-size: 16px; 84 | font-family: var(--font-mono); 85 | background-color: rgba(255, 255, 255, 0.45); 86 | border-radius: 3px; 87 | box-shadow: 2px 2px 6px rgb(255 255 255 / 25%); 88 | padding: 0.5em; 89 | overflow-x: auto; 90 | color: var(--text-color); 91 | } 92 | 93 | input, 94 | button { 95 | font-size: inherit; 96 | font-family: inherit; 97 | } 98 | 99 | button:focus:not(:focus-visible) { 100 | outline: none; 101 | } 102 | 103 | @media (min-width: 720px) { 104 | h1 { 105 | font-size: 2.4rem; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs#typescript 2 | // for information about these interfaces 3 | declare global { 4 | namespace App { 5 | // interface Error {} 6 | 7 | interface Locals { 8 | // sveltekit default 9 | userid: string; 10 | 11 | // laravel sanctum 12 | user: any; 13 | session: string; 14 | } 15 | 16 | interface Session { 17 | // laravel sanctum 18 | user: any; 19 | } 20 | 21 | // interface PageData {} 22 | // interface Platform {} 23 | } 24 | } 25 | 26 | export { }; 27 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/hooks/laravel-sanctum-fake-logged-in.ts: -------------------------------------------------------------------------------- 1 | import cookie, { parse } from 'cookie'; 2 | import type { Handle } from '@sveltejs/kit'; 3 | 4 | // inside laravel-sanctum.ts 5 | // -> we're actually fetching the user who logged in 6 | // -> as well fetching a new session if the cookie is not present 7 | export const handle: Handle = async ({ event, resolve }) => { 8 | if (!event.locals.user) { 9 | event.locals.user = { 10 | id: 1, 11 | email: "janedoe@email.com", 12 | photo: "https://images.unsplash.com/photo-1502378735452-bc7d86632805?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=aa3a807e1bbdfd4364d1f449eaa96d82", 13 | first_name: "Jane", 14 | last_name: "Doe", 15 | } 16 | } 17 | 18 | const sessionName = import.meta.env.VITE_SESSION_NAME 19 | const cookies = cookie.parse(event.request.headers.get('cookie') || '') 20 | event.locals.session = cookies[sessionName] 21 | 22 | const response = await resolve(event) 23 | 24 | if (!event.locals.session) { 25 | // set cookie in the client 26 | response.headers.set( 27 | 'set-cookie', 28 | cookie.serialize(import.meta.env.VITE_SESSION_NAME, "this-is-a-fake-session") 29 | ) 30 | } 31 | 32 | return response 33 | }; 34 | -------------------------------------------------------------------------------- /src/hooks/laravel-sanctum-fake-logged-out.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit'; 2 | 3 | // since we want to simulate a FAKE log out 4 | // inside this hooks, we will do nothing! 5 | export const handle: Handle = async ({ event, resolve }) => { 6 | const response = await resolve(event) 7 | return response 8 | }; 9 | -------------------------------------------------------------------------------- /src/hooks/laravel-sanctum.ts: -------------------------------------------------------------------------------- 1 | import { api } from '$src/routes/api'; 2 | import cookie, { parse } from 'cookie'; 3 | import type { Handle } from '@sveltejs/kit'; 4 | 5 | export const handle: Handle = async ({ event, resolve }) => { 6 | if (!event.locals.user) { 7 | const loggedIn = await api({ 8 | method: 'get', 9 | resource: 'logged-in', 10 | event, 11 | }); 12 | event.locals.user = (await loggedIn.json()).user 13 | } 14 | 15 | const sessionName = import.meta.env.VITE_SESSION_NAME 16 | const cookies = cookie.parse(event.request.headers.get('cookie') || '') 17 | event.locals.session = cookies[sessionName] 18 | 19 | const response = await resolve(event) 20 | 21 | if (!event.locals.session) { 22 | const sanctum = await api({ 23 | method: 'get', 24 | resource: 'sanctum/csrf-cookie', 25 | event, 26 | }); 27 | 28 | if (sanctum.status === 204) { 29 | // set cookie in the client 30 | response.headers.set( 31 | 'set-cookie', 32 | sanctum.headers.get('set-cookie') ?? '' 33 | ) 34 | } 35 | } 36 | 37 | return response 38 | }; 39 | -------------------------------------------------------------------------------- /src/hooks/sveltekit-default.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit'; 2 | import * as cookie from 'cookie'; 3 | 4 | export const handle: Handle = async ({ event, resolve }) => { 5 | const cookies = cookie.parse(event.request.headers.get('cookie') || ''); 6 | event.locals.userid = cookies['userid'] || crypto.randomUUID(); 7 | 8 | const response = await resolve(event); 9 | 10 | if (!cookies['userid']) { 11 | // if this is the first time the user has visited this app, 12 | // set a cookie so that we recognise them when they return 13 | response.headers.set( 14 | 'set-cookie', 15 | cookie.serialize('userid', event.locals.userid, { 16 | path: '/', 17 | httpOnly: true 18 | }) 19 | ); 20 | } 21 | 22 | return response; 23 | }; 24 | -------------------------------------------------------------------------------- /src/lib/Counter.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
17 | 22 | 23 |
24 |
25 | 26 | {Math.floor($displayed_count)} 27 |
28 |
29 | 30 | 35 |
36 | 37 | 104 | -------------------------------------------------------------------------------- /src/lib/components/Accordion.svelte: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | -------------------------------------------------------------------------------- /src/lib/components/AccordionItem.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | 31 | {#if show} 32 |
33 | 34 |
35 | {/if} 36 |
37 | -------------------------------------------------------------------------------- /src/lib/components/Alert.svelte: -------------------------------------------------------------------------------- 1 | 36 | 37 |
40 | {#if body} 41 | {body} 42 | {:else} 43 | 44 | {/if} 45 |
46 | -------------------------------------------------------------------------------- /src/lib/components/Badge.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | {#if body} 12 | {body} 13 | {:else} 14 | 15 | {/if} 16 | 17 | -------------------------------------------------------------------------------- /src/lib/components/Breadcrumb.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Breadcrumb.svelte -------------------------------------------------------------------------------- /src/lib/components/ButtonGroup.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/ButtonGroup.svelte -------------------------------------------------------------------------------- /src/lib/components/Buttons.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Buttons.svelte -------------------------------------------------------------------------------- /src/lib/components/Card.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Card.svelte -------------------------------------------------------------------------------- /src/lib/components/Carousel.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Carousel.svelte -------------------------------------------------------------------------------- /src/lib/components/CloseButton.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/CloseButton.svelte -------------------------------------------------------------------------------- /src/lib/components/Code.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | {#if language} 10 | // {language} 11 | {:else} 12 | 13 | {/if} 14 | 15 | {#if data.length} 16 | {#each data as datum, i} 17 |
{datum}
18 | 19 | {#if data.length !== i + 1} 20 |
21 | {/if} 22 | {/each} 23 | {:else} 24 | 25 | {/if} 26 |
27 | -------------------------------------------------------------------------------- /src/lib/components/Collapse.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Collapse.svelte -------------------------------------------------------------------------------- /src/lib/components/Docs/DocAccordion.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | Accordion 8 | 9 | Eu laboris officia dolore non anim qui fugiat duis. Consectetur anim consequat commodo 11 | excepteur dolor commodo sint proident eu deserunt ea incididunt minim sint. Aliqua dolor tempor 12 | ex dolore magna tempor ullamco sunt sit sit veniam. Nisi proident cupidatat labore aliqua minim. 13 | Eiusmod ad laborum commodo elit anim cupidatat elit quis. 15 | 16 | My 2nd accordition with html element 17 |
18 |

19 | Esse labore dolore reprehenderit est laboris labore. Deserunt pariatur nisi enim nulla elit 20 | minim laborum sunt sunt labore duis sit. Dolore incididunt minim eu est dolor velit 21 | adipisicing deserunt labore. Culpa aute nostrud magna aliqua exercitation reprehenderit sunt 22 | sit. 23 |

24 | strong 25 | italic 26 |
27 |
28 |
29 | 30 |

Example:

31 | 32 | {"import Accordion from '$lib/components/Accordion.svelte'"}
33 | {"import AccordionItem from '$lib/components/AccordionItem.svelte'"}

34 | {'// can be (primary, secondary, success, danger, warning, info, light, dark)'}
35 | {"let type = 'danger'"}
36 |
37 | {''}
38 |   {'Text or HTML element here..
'}
39 |   {'Text or HTML element here..'}
41 | {''} 42 |
43 | -------------------------------------------------------------------------------- /src/lib/components/Docs/DocAlert.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | Alerts 7 | A simple primary alert 8 | A simple secondary alert 9 | A simple success alert 10 | A simple danger alert 11 | A simple warning alert 12 | A simple info alert 13 | A simple light alert 14 | A simple dark alert 15 | 16 |

Example:

17 | 18 | {"import Alert from '$lib/components/Alert.svelte'"}

19 | {''}
20 | {'A simple primary alert'} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/Docs/DocBadge.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | Badges 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Hello World! 18 |
19 | 20 |

Example:

21 | 22 | {"import Badge from '$lib/components/Badge.svelte'"}

23 | {''}
24 | {''}
25 | {''}
26 | {''}
27 | {''}
28 | {''}
29 | {''}
30 | {''}
31 | {'Hello World!'} 32 |
33 | -------------------------------------------------------------------------------- /src/lib/components/Dropdowns.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Dropdowns.svelte -------------------------------------------------------------------------------- /src/lib/components/ListGroup.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/ListGroup.svelte -------------------------------------------------------------------------------- /src/lib/components/Modal.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Modal.svelte -------------------------------------------------------------------------------- /src/lib/components/NavsAndTabs.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/NavsAndTabs.svelte -------------------------------------------------------------------------------- /src/lib/components/Pagination.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Pagination.svelte -------------------------------------------------------------------------------- /src/lib/components/Popovers.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Popovers.svelte -------------------------------------------------------------------------------- /src/lib/components/Spinners.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Spinners.svelte -------------------------------------------------------------------------------- /src/lib/components/Toasts.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Toasts.svelte -------------------------------------------------------------------------------- /src/lib/components/Tooltips.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/components/Tooltips.svelte -------------------------------------------------------------------------------- /src/lib/form.ts: -------------------------------------------------------------------------------- 1 | import { invalidateAll } from '$app/navigation'; 2 | 3 | // this action (https://svelte.dev/tutorial/actions) allows us to 4 | // progressively enhance a
that already works without JS 5 | export function enhance( 6 | form: HTMLFormElement, 7 | { 8 | pending, 9 | error, 10 | result 11 | }: { 12 | pending?: ({ data, form }: { data: FormData; form: HTMLFormElement }) => void; 13 | error?: ({ 14 | data, 15 | form, 16 | response, 17 | error 18 | }: { 19 | data: FormData; 20 | form: HTMLFormElement; 21 | response: Response | null; 22 | error: Error | null; 23 | }) => void; 24 | result?: ({ 25 | data, 26 | form, 27 | response 28 | }: { 29 | data: FormData; 30 | response: Response; 31 | form: HTMLFormElement; 32 | }) => void; 33 | } = {} 34 | ) { 35 | let current_token: unknown; 36 | 37 | async function handle_submit(event: SubmitEvent) { 38 | const token = (current_token = {}); 39 | 40 | event.preventDefault(); 41 | 42 | const data = new FormData(form); 43 | 44 | if (pending) pending({ data, form }); 45 | 46 | try { 47 | const response = await fetch(form.action, { 48 | method: form.method, 49 | headers: { 50 | accept: 'application/json' 51 | }, 52 | body: data 53 | }); 54 | 55 | if (token !== current_token) return; 56 | 57 | if (response.ok) { 58 | if (result) result({ data, form, response }); 59 | invalidateAll(); 60 | } else if (error) { 61 | error({ data, form, error: null, response }); 62 | } else { 63 | console.error(await response.text()); 64 | } 65 | } catch (err: unknown) { 66 | if (error && err instanceof Error) { 67 | error({ data, form, error: err, response: null }); 68 | } else { 69 | throw err; 70 | } 71 | } 72 | } 73 | 74 | form.addEventListener('submit', handle_submit); 75 | 76 | return { 77 | destroy() { 78 | form.removeEventListener('submit', handle_submit); 79 | } 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /src/lib/header/Header.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 |
8 | 9 | SvelteKit 10 | 11 |
12 | 13 | 32 | 33 |
34 | 35 |
36 |
37 | 38 | 127 | -------------------------------------------------------------------------------- /src/lib/header/svelte-logo.svg: -------------------------------------------------------------------------------- 1 | svelte-logo -------------------------------------------------------------------------------- /src/lib/images/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 16 | -------------------------------------------------------------------------------- /src/lib/images/svelte-logo.svg: -------------------------------------------------------------------------------- 1 | svelte-logo -------------------------------------------------------------------------------- /src/lib/images/svelte-welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/images/svelte-welcome.png -------------------------------------------------------------------------------- /src/lib/images/svelte-welcome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/images/svelte-welcome.webp -------------------------------------------------------------------------------- /src/lib/ioevents/click.ts: -------------------------------------------------------------------------------- 1 | /** Dispatch event on click outside of node */ 2 | export function clickOutside(node: any, except: any[] = []) { 3 | const handle = (event: any) => { 4 | let shouldSkip = false 5 | 6 | except.forEach((val) => { 7 | if (document.getElementById(val)?.contains(event.target)) { 8 | shouldSkip = true 9 | } 10 | }) 11 | 12 | if (shouldSkip) { 13 | return 14 | } 15 | 16 | if (node && !node.contains(event.target) && !event.defaultPrevented) { 17 | node.dispatchEvent(new CustomEvent('click-outside', node)) 18 | } 19 | } 20 | 21 | document.addEventListener('click', handle, true) 22 | 23 | return { 24 | destroy() { 25 | document.removeEventListener('click', handle, true) 26 | }, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/lib/ioevents/keydown.ts: -------------------------------------------------------------------------------- 1 | /** Dispatch event on keydown Escape of node */ 2 | export function keydownEscape(node: any) { 3 | const handle = (event: any) => { 4 | if (event.key === 'Escape') { 5 | node.dispatchEvent(new CustomEvent('keydown-escape', node)) 6 | } 7 | } 8 | 9 | document.addEventListener('keydown', handle, true) 10 | 11 | return { 12 | destroy() { 13 | document.removeEventListener('keydown', handle, true) 14 | }, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/lib/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .bg-blog { 6 | @apply bg-blue-500; 7 | } 8 | 9 | .primary { 10 | @apply text-purple-100 bg-purple-600; 11 | } 12 | 13 | .secondary { 14 | @apply text-gray-100 bg-gray-500; 15 | } 16 | 17 | .success { 18 | @apply text-green-100 bg-green-600; 19 | } 20 | 21 | .danger { 22 | @apply text-red-100 bg-red-600; 23 | } 24 | 25 | .warning { 26 | @apply text-orange-100 bg-orange-600; 27 | } 28 | 29 | .info { 30 | @apply text-blue-100 bg-blue-600; 31 | } 32 | 33 | .light { 34 | @apply text-gray-700 bg-white; 35 | } 36 | 37 | .dark { 38 | @apply text-gray-100 bg-gray-700; 39 | } 40 | -------------------------------------------------------------------------------- /src/lib/templates/Admin/API/form.ts: -------------------------------------------------------------------------------- 1 | export default function enhance( 2 | form: HTMLFormElement, 3 | { 4 | pending, 5 | error, 6 | result, 7 | }: { 8 | pending?: (data: FormData, form: HTMLFormElement) => void 9 | error?: (res: Response, error: Error, form: HTMLFormElement) => void 10 | result: (res: Response, form: HTMLFormElement) => void 11 | } 12 | ) { 13 | async function handle(e: Event) { 14 | e.preventDefault() 15 | 16 | const body = new FormData(form) 17 | 18 | if (pending) pending(body, form) 19 | 20 | try { 21 | const res = await fetch(form.action, { 22 | method: form.method, 23 | headers: { 24 | accept: 'application/json', 25 | }, 26 | body, 27 | }) 28 | 29 | if (res.ok) { 30 | result(res, form) 31 | } else if (error) { 32 | error(res, null, form) 33 | } else { 34 | console.error(await res.text()) 35 | } 36 | } catch (e) { 37 | if (error) { 38 | error(null, e, form) 39 | } else { 40 | throw e 41 | } 42 | } 43 | } 44 | 45 | form.addEventListener('submit', handle) 46 | 47 | return { 48 | destroy() { 49 | form.removeEventListener('submit', handle) 50 | }, 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/lib/templates/Admin/Config/charts.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * For usage, visit Chart.js docs https://www.chartjs.org/docs/latest/ 3 | */ 4 | export const barConfig = { 5 | type: 'bar', 6 | data: { 7 | labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], 8 | datasets: [ 9 | { 10 | label: 'Shoes', 11 | backgroundColor: '#0694a2', 12 | // borderColor: window.chartColors.red, 13 | borderWidth: 1, 14 | data: [-3, 14, 52, 74, 33, 90, 70], 15 | }, 16 | { 17 | label: 'Bags', 18 | backgroundColor: '#7e3af2', 19 | // borderColor: window.chartColors.blue, 20 | borderWidth: 1, 21 | data: [66, 33, 43, 12, 54, 62, 84], 22 | }, 23 | ], 24 | }, 25 | options: { 26 | responsive: true, 27 | legend: { 28 | display: false, 29 | }, 30 | }, 31 | } 32 | 33 | export const lineConfig = { 34 | type: 'line', 35 | data: { 36 | labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], 37 | datasets: [ 38 | { 39 | label: 'Organic', 40 | /** 41 | * These colors come from Tailwind CSS palette 42 | * https://tailwindcss.com/docs/customizing-colors/#default-color-palette 43 | */ 44 | backgroundColor: '#0694a2', 45 | borderColor: '#0694a2', 46 | data: [43, 48, 40, 54, 67, 73, 70], 47 | fill: false, 48 | }, 49 | { 50 | label: 'Paid', 51 | fill: false, 52 | /** 53 | * These colors come from Tailwind CSS palette 54 | * https://tailwindcss.com/docs/customizing-colors/#default-color-palette 55 | */ 56 | backgroundColor: '#7e3af2', 57 | borderColor: '#7e3af2', 58 | data: [24, 50, 64, 74, 52, 51, 65], 59 | }, 60 | ], 61 | }, 62 | options: { 63 | responsive: true, 64 | /** 65 | * Default legends are ugly and impossible to style. 66 | * See examples in charts.html to add your own legends 67 | * */ 68 | legend: { 69 | display: false, 70 | }, 71 | tooltips: { 72 | mode: 'index', 73 | intersect: false, 74 | }, 75 | hover: { 76 | mode: 'nearest', 77 | intersect: true, 78 | }, 79 | scales: { 80 | x: { 81 | display: true, 82 | scaleLabel: { 83 | display: true, 84 | labelString: 'Month', 85 | }, 86 | }, 87 | y: { 88 | display: true, 89 | scaleLabel: { 90 | display: true, 91 | labelString: 'Value', 92 | }, 93 | }, 94 | }, 95 | }, 96 | } 97 | 98 | export const pieConfig = { 99 | type: 'doughnut', 100 | data: { 101 | datasets: [ 102 | { 103 | data: [33, 33, 33], 104 | /** 105 | * These colors come from Tailwind CSS palette 106 | * https://tailwindcss.com/docs/customizing-colors/#default-color-palette 107 | */ 108 | backgroundColor: ['#0694a2', '#1c64f2', '#7e3af2'], 109 | label: 'Dataset 1', 110 | }, 111 | ], 112 | labels: ['Shoes', 'Shirts', 'Bags'], 113 | }, 114 | options: { 115 | responsive: true, 116 | cutoutPercentage: 80, 117 | /** 118 | * Default legends are ugly and impossible to style. 119 | * See examples in charts.html to add your own legends 120 | * */ 121 | legend: { 122 | display: false, 123 | }, 124 | }, 125 | } 126 | -------------------------------------------------------------------------------- /src/lib/templates/Admin/Header.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 |
21 |
24 | 25 | 39 | {#if withSearch} 40 | 41 |
42 |
43 |
44 | 51 |
52 | 58 |
59 |
60 | {/if} 61 | 62 |
63 | 230 |
231 |
232 |
233 | -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/create-account-office-dark.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Admin/Images/create-account-office-dark.jpeg -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/create-account-office.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Admin/Images/create-account-office.jpeg -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Admin/Images/dashboard.png -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/forgot-password-office-dark.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Admin/Images/forgot-password-office-dark.jpeg -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/forgot-password-office.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Admin/Images/forgot-password-office.jpeg -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/login-office-dark.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Admin/Images/login-office-dark.jpeg -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/login-office.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Admin/Images/login-office.jpeg -------------------------------------------------------------------------------- /src/lib/templates/Admin/Images/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/templates/Admin/SideBar.svelte: -------------------------------------------------------------------------------- 1 | 90 | 91 |
92 | {#if withTitle} 93 | {appName} 94 | {/if} 95 | 183 |
184 | -------------------------------------------------------------------------------- /src/lib/templates/Admin/ToggleTheme.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 27 | -------------------------------------------------------------------------------- /src/lib/templates/Blog/Config/links.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Home", 4 | "url": "/" 5 | }, 6 | { 7 | "name": "Resumé", 8 | "url": "/resume" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /src/lib/templates/Blog/Config/particle.json: -------------------------------------------------------------------------------- 1 | { 2 | "particles": { 3 | "number": { 4 | "value": 24, 5 | "density": { 6 | "enable": true, 7 | "value_area": 800 8 | } 9 | }, 10 | "color": { 11 | "value": "#ffffff" 12 | }, 13 | "shape": { 14 | "type": "circle", 15 | "stroke": { 16 | "width": 0, 17 | "color": "#000000" 18 | }, 19 | "polygon": { 20 | "nb_sides": 12 21 | }, 22 | "image": { 23 | "src": "img/github.svg", 24 | "width": 100, 25 | "height": 100 26 | } 27 | }, 28 | "opacity": { 29 | "value": 0.3, 30 | "random": false, 31 | "anim": { 32 | "enable": false, 33 | "speed": 1, 34 | "opacity_min": 0.1, 35 | "sync": false 36 | } 37 | }, 38 | "size": { 39 | "value": 3, 40 | "random": true, 41 | "anim": { 42 | "enable": false, 43 | "speed": 40, 44 | "size_min": 0.1, 45 | "sync": false 46 | } 47 | }, 48 | "line_linked": { 49 | "enable": true, 50 | "distance": 150, 51 | "color": "#ffffff", 52 | "opacity": 0.4, 53 | "width": 1 54 | }, 55 | "move": { 56 | "enable": true, 57 | "speed": 0.5, 58 | "direction": "top-right", 59 | "random": true, 60 | "straight": false, 61 | "out_mode": "out", 62 | "bounce": false, 63 | "attract": { 64 | "enable": true, 65 | "rotateX": 600, 66 | "rotateY": 1200 67 | } 68 | } 69 | }, 70 | "interactivity": { 71 | "detect_on": "canvas", 72 | "events": { 73 | "onhover": { 74 | "enable": false, 75 | "mode": "repulse" 76 | }, 77 | "onclick": { 78 | "enable": false, 79 | "mode": "push" 80 | }, 81 | "resize": true 82 | }, 83 | "modes": { 84 | "grab": { 85 | "distance": 400, 86 | "line_linked": { 87 | "opacity": 1 88 | } 89 | }, 90 | "bubble": { 91 | "distance": 400, 92 | "size": 40, 93 | "duration": 2, 94 | "opacity": 5, 95 | "speed": 3 96 | }, 97 | "repulse": { 98 | "distance": 200, 99 | "duration": 0.4 100 | }, 101 | "push": { 102 | "particles_nb": 4 103 | }, 104 | "remove": { 105 | "particles_nb": 2 106 | } 107 | } 108 | }, 109 | "retina_detect": true 110 | } 111 | -------------------------------------------------------------------------------- /src/lib/templates/Blog/Header.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 |
10 | 11 | 23 | 32 |
33 |
34 | -------------------------------------------------------------------------------- /src/lib/templates/Blog/Images/company1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Blog/Images/company1.png -------------------------------------------------------------------------------- /src/lib/templates/Blog/Images/company3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Blog/Images/company3.png -------------------------------------------------------------------------------- /src/lib/templates/Blog/Images/company4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daison12006013/sveltekit-starter/e761b9f3946352b1624f5200b4c0461a5b633ac1/src/lib/templates/Blog/Images/company4.jpeg -------------------------------------------------------------------------------- /src/lib/templates/Blog/Particles/Particles.svelte: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63 | 64 |
65 | -------------------------------------------------------------------------------- /src/lib/templates/Blog/Particles/global.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /src/lib/templates/Blog/Particles/index.d.ts: -------------------------------------------------------------------------------- 1 | import type { SvelteComponentTyped } from "svelte"; 2 | import type { ISourceOptions, Engine, Container } from "tsparticles-engine"; 3 | 4 | declare module "svelte-particles" { 5 | type CustomEventWrapper = { 6 | [K in keyof T]: CustomEvent; 7 | }; 8 | type ParticlesProps = { 9 | options?: ISourceOptions; 10 | url?: string; 11 | id?: string; 12 | particlesInit: (engine: Engine) => Promise; 13 | }; 14 | type ParticlesEvents = CustomEventWrapper<{ 15 | particlesLoaded: { 16 | particles?: Container; 17 | }; 18 | }>; 19 | export default class extends SvelteComponentTyped { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/lib/templates/Blog/Particles/index.ts: -------------------------------------------------------------------------------- 1 | export { default as default } from './Particles.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/templates/Blog/SideBar.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 |
20 | 44 |
45 | -------------------------------------------------------------------------------- /src/lib/translator.ts: -------------------------------------------------------------------------------- 1 | const getLang = (): string => { 2 | // well, maybe base the language from 3 | // -> where the guest coming from? via API to determine their IP Address 4 | // -> or when they're logged in, base it from their 5 | // preferred language by storing that in the hooks 6 | // ohh, you should cache that too, :P 7 | 8 | return 'en' 9 | } 10 | 11 | const getData = (lang: string) => { 12 | // ofcourse get the data via api, below is just a sample! 13 | 14 | const data = { 15 | en: { 16 | Dashboard: 'Dashboard', 17 | 'Lorem :ipsum whatever': ':ipsum Lorem Sikador', 18 | 'Lorem {ipsum} whatever': '{ipsum} Lorem Sikador', 19 | }, 20 | } 21 | 22 | return data[lang] 23 | } 24 | 25 | export const trans = (text: string, replacers?: any, strict = false): string => { 26 | const lang = getLang() 27 | const data = getData(lang) 28 | 29 | let resp = data[text] 30 | 31 | if (resp === undefined) { 32 | if (strict) { 33 | throw Error(`Translation for ${text} not found under [${lang}] language.`) 34 | } 35 | 36 | resp = text 37 | } 38 | 39 | if (replacers !== undefined) { 40 | Object.keys(replacers).forEach((idx) => { 41 | resp = resp.replace(`:${idx}`, replacers[idx]) // Laravel like translations... 42 | resp = resp.replace(`{${idx}}`, replacers[idx]) // maybe uses curly braces? "My {text} whatever" 43 | }) 44 | } 45 | 46 | return resp 47 | } 48 | 49 | export default trans 50 | -------------------------------------------------------------------------------- /src/routes/admin/(authenticated)/+layout.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 |
24 |
25 | 26 | 31 | 32 | 33 | 34 | {#if $isSideMenuOpen} 35 |
38 | 47 | {/if} 48 | 49 |
50 |
51 | 52 | 53 |
54 |
55 |
56 | -------------------------------------------------------------------------------- /src/routes/admin/(authenticated)/buttons/+page.svelte: -------------------------------------------------------------------------------- 1 | 2 | Buttons 3 | 4 | 5 |
6 |
7 |

Buttons

8 | 9 | 13 |
14 | 15 | 18 | 19 | Star this project on GitHub 20 |
21 | View more → 22 |
23 | 24 | 25 |

Sizes

26 |
27 | 28 |
29 | 34 |
35 | 36 | 37 |
38 | 43 |
44 | 45 | 46 |
47 | 52 |
53 | 54 | 55 |
56 | 62 | 67 |
68 | 69 | 70 |
71 | 76 |
77 |
78 |

79 | Apply 80 | w-full 81 | to any button to create a block level button. 82 |

83 | 84 | 85 |

Icons

86 |
87 | 88 |
89 | 106 |
107 | 108 | 109 |
110 | 127 |
128 | 129 | 130 |
131 | 143 |
144 | 145 | 146 |
147 | 157 |
158 |
159 |
160 |
161 | -------------------------------------------------------------------------------- /src/routes/admin/(authenticated)/cards/+page.svelte: -------------------------------------------------------------------------------- 1 | 2 | Cards 3 | 4 | 5 |
6 |
7 |

Cards

8 | 9 | 13 |
14 | 15 | 18 | 19 | Star this project on GitHub 20 |
21 | View more → 22 |
23 | 24 | 25 |

Big section cards

26 |
27 |

Large, full width sections goes here

28 |
29 | 30 | 31 |

Responsive cards

32 |
33 | 34 |
35 |
38 | 39 | 42 | 43 |
44 |
45 |

Total clients

46 |

6389

47 |
48 |
49 | 50 |
51 |
54 | 55 | 60 | 61 |
62 |
63 |

Account balance

64 |

$ 46,760.89

65 |
66 |
67 | 68 |
69 |
72 | 73 | 76 | 77 |
78 |
79 |

New sales

80 |

376

81 |
82 |
83 | 84 |
85 |
88 | 89 | 94 | 95 |
96 |
97 |

Pending contacts

98 |

35

99 |
100 |
101 |
102 | 103 | 104 |

Cards with title

105 |
106 |
107 |

Revenue

108 |

109 | Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga, cum commodi a omnis 110 | numquam quod? Totam exercitationem quos hic ipsam at qui cum numquam, sed amet ratione! 111 | Ratione, nihil dolorum. 112 |

113 |
114 |
115 |

Colored card

116 |

117 | Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga, cum commodi a omnis 118 | numquam quod? Totam exercitationem quos hic ipsam at qui cum numquam, sed amet ratione! 119 | Ratione, nihil dolorum. 120 |

121 |
122 |
123 |
124 |
125 | -------------------------------------------------------------------------------- /src/routes/admin/(authenticated)/charts/+page.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | {_i('Charts')} 12 | 13 | 14 |
15 |
16 |

Charts

17 | 18 | 22 |
23 | 24 | 27 | 28 | {_i('Star this project on GitHub')} 29 |
30 | {_i('View more')} → 31 |
32 | 33 |

34 | {_i('Charts are provided by')} 35 | 39 | {_i('Chart.js')} 40 | 41 | . {_i( 42 | 'Note that the default legends are disabled and you should provide a description for your charts in HTML. See source code for examples.' 43 | )} 44 |

45 | 46 |
47 | 48 |
49 |

Doughnut/Pie

50 | 51 |
52 | 53 |
54 | 55 | {_i('Shirts')} 56 |
57 |
58 | 59 | {_i('Shoes')} 60 |
61 |
62 | 63 | {_i('Bags')} 64 |
65 |
66 |
67 | 68 |
69 |

Lines

70 | 71 |
72 | 73 |
74 | 75 | Organic 76 |
77 |
78 | 79 | Paid 80 |
81 |
82 |
83 | 84 |
85 |

Bars

86 | 87 |
88 | 89 |
90 | 91 | {_i('Shoes')} 92 |
93 |
94 | 95 | {_i('Bags')} 96 |
97 |
98 |
99 |
100 |
101 |
102 | -------------------------------------------------------------------------------- /src/routes/admin/(authenticated)/components/+page.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 | 28 | Components 29 | 30 | 31 |
32 |
33 |
34 |
35 | 36 |
37 | 38 |
39 | 40 |
41 | 42 |
43 | 44 |
45 | 46 |
47 | 48 |
49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
68 |
69 |
70 | 71 | 78 | -------------------------------------------------------------------------------- /src/routes/admin/(authenticated)/forms/+page.svelte: -------------------------------------------------------------------------------- 1 | 2 | Forms 3 | 4 | 5 |
6 |
7 |

Forms

8 | 9 | 13 |
14 | 15 | 18 | 19 | Star this project on GitHub 20 |
21 | View more → 22 |
23 | 24 | 25 |

Elements

26 |
27 | 34 | 35 |
36 | Account Type 37 |
38 | 47 | 56 |
57 |
58 | 59 | 70 | 71 | 84 | 85 |