Skip to content

Instantly share code, notes, and snippets.

@WalterWoshid
Last active February 17, 2023 14:51
Show Gist options
  • Save WalterWoshid/388406994e23c2e40be19b2b8c10917f to your computer and use it in GitHub Desktop.
Save WalterWoshid/388406994e23c2e40be19b2b8c10917f to your computer and use it in GitHub Desktop.
Laravel 9 + Vue 3 + Tailwind CSS 3 + TypeScript + Sail (Docker) + Ziggy + Hot Module Replacement / BrowserSync

Laravel Docker Starter

Laravel 9, Vue 3, Tailwind CSS 3, TypeScript, Sail (Docker), Ziggy, Hot Module Replacement / BrowserSync

Twitter: @WalterWoshid

This is a working template for:

  • Laravel 9
  • Vue 3
  • Tailwind CSS 3
  • TypeScript
    • Full support for @/... paths and autocompletions
  • Sail (Docker)
  • Ziggy
    • Full support with TypeScript for Autocompletion (PhpStorm doesn't like Ziggy that much)
  • Hot Module Replacement
  • BrowserSync
  • Ignition/Flare config for PhpStorm / VSCode (only WSL2 tested)
# This is for Ignition (the error page), so you can click the pen next to the line numbers
# and it will open the code in your IDE (only tested for WSL2)
# WSL2 - VSCode (Remote)
IGNITION_EDITOR=vscode-remote
IGNITION_LOCAL_SITES_PATH="wsl+Ubuntu-20.04/home/path/to/project"
IGNITION_REMOTE_SITES_PATH=/var/www/html
# WSL2 - VSCode (Local)
IGNITION_EDITOR=vscode
IGNITION_LOCAL_SITES_PATH=/wsl$/Ubuntu-20.04/home/walter/Projects/PHP/my-project
# WSL2 - PhpStorm
IGNITION_EDITOR=phpstorm
IGNITION_LOCAL_SITES_PATH=//wsl$/Ubuntu-20.04/home/walter/Projects/PHP/my-project
IGNITION_REMOTE_SITES_PATH=/var/www/html
<template>
<h1>{{ hello }}</h1>
</template>
<script setup lang="ts">
const hello = "Hello world!"
</script>
"require": {
"php": "^8.1",
"ext-pdo": "*",
"guzzlehttp/guzzle": "^7.2",
"inertiajs/inertia-laravel": "^0.5.4",
"laravel/framework": "^9.2",
"laravel/sanctum": "^2.8",
"laravel/tinker": "^2.7",
"tightenco/ziggy": "^1.0"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.12",
"fakerphp/faker": "^1.9.1",
"laravel/breeze": "^1.8",
"laravel/sail": "^1.0.1",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^6.1",
"phpunit/phpunit": "^9.5.10",
"spatie/laravel-ignition": "^1.0"
},
# Sail
services:
laravel.test:
...
ports:
- '80:80'
- '8080:8080' # THIS PORT IS IMPORTANT FOR HOT MODULE REPLACEMENT
...
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["resources/js/*"],
"ziggy": ["vendor/tightenco/ziggy/src/js/index.js"],
"ziggyRoute": ["vendor/tightenco/ziggy/src/js/Router.js"],
"ziggyVue": ["vendor/tightenco/ziggy/src/js/vue.js"]
}
},
"exclude": ["node_modules", "public"]
}
"devDependencies": {
"@inertiajs/inertia": "^0.11.0",
"@inertiajs/inertia-vue3": "^0.6.0",
"@inertiajs/progress": "^0.2.6",
"@tailwindcss/forms": "^0.4.0",
"@vue/compiler-sfc": "^3.2.30",
"autoprefixer": "^10.4.2",
"axios": "^0.25",
"browser-sync": "^2.27.8",
"browser-sync-webpack-plugin": "^2.3.0",
"laravel-mix": "^6.0.6",
"lodash": "^4.17.19",
"normalize.css": "^8.0.1",
"postcss": "^8.4.6",
"postcss-import": "^14.0.2",
"postcss-omit-import-tilde": "^1.0.1",
"tailwindcss": "^3.0.18",
"ts-loader": "^9.2.8",
"typescript": "^4.6.2",
"vue": "^3.2.30",
"vue-loader": "^16.1.2"
}
/* Tailwind CSS */
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
/* CSS Reset */
@import '~normalize.css/normalize.css';
import _ from 'lodash'
import axios from 'axios'
import ZiggyRoute from 'ziggyRoute'
export declare global {
// noinspection JSUnusedGlobalSymbols
interface Window {
_: typeof _
axios: typeof axios
route: typeof ZiggyRoute
}
const _: typeof _
const axios: typeof axios
const route: typeof ZiggyRoute
}
declare module '*.vue' {
import { defineComponent } from 'vue'
// noinspection JSUnusedGlobalSymbols
export default defineComponent
}
// Bootstrap the application (Lodash, axios, pusher)
require('./bootstrap')
// Vue
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/inertia-vue3'
import { App } from '@vue/runtime-core'
// Ziggy routes
import route from 'ziggy'
window.route = route
import { ZiggyVue } from 'ziggyVue'
// Title
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'My Project'
// Create app
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => require(`./Pages/${name}.vue`),
setup({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
.use(plugin, ZiggyVue)
.mixin({ methods: { route: window.route } })
.mount(el) as unknown as App
},
})
// Inertia progress bar
import { InertiaProgress } from '@inertiajs/progress'
InertiaProgress.init({ color: '#4B5563' })
// Lodash
window._ = require('lodash')
// Axios
window.axios = require('axios')
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
// Echo / Pusher
// import Echo from 'laravel-echo'
// window.Pusher = require('pusher-js')
// window.Echo = new Echo({
// broadcaster: 'pusher',
// key: process.env.MIX_PUSHER_APP_KEY,
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
// forceTLS: true
// })
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">
<!-- Styles -->
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
<!-- Scripts -->
@routes
<script src="{{ mix('js/app.js') }}" defer></script>
</head>
<body class="font-sans antialiased">
@inertia
</body>
</html>
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
'./resources/js/**/*.vue',
],
theme: {
extend: {
fontFamily: {
sans: ['Nunito', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [require('@tailwindcss/forms')],
}
{
"compilerOptions": {
"target": "es5",
"module": "es2020",
"moduleResolution": "node",
"baseUrl": "./",
"strict": true,
"skipLibCheck": true,
"noImplicitAny": false,
"paths": {
"@/*": ["resources/js/*"],
"ziggy": ["vendor/tightenco/ziggy/src/js/index.js"],
"ziggyRoute": ["vendor/tightenco/ziggy/src/js/Router.js"],
"ziggyVue": ["vendor/tightenco/ziggy/src/js/vue.js"]
},
"typeRoots": [
"resources/@types",
"node_modules/@types"
]
},
"include": ["resources/js/**/*"]
}
const path = require('path')
module.exports = {
resolve: {
alias: {
'@': path.resolve('resources/js'),
ziggy: path.resolve('vendor/tightenco/ziggy/src/js/index.js'),
ziggyRoute: path.resolve('vendor/tightenco/ziggy/src/js/Router.js'),
ziggyVue: path.resolve('vendor/tightenco/ziggy/src/js/vue.js'),
},
},
devServer: {
host: '0.0.0.0',
port: '8080',
},
}
const mix = require('laravel-mix')
mix.ts('resources/js/app.ts', 'public/js')
.vue()
.postCss('resources/css/app.css', 'public/css', [
require('postcss-omit-import-tilde'),
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
])
.webpackConfig(require('./webpack.config'))
.sourceMaps(false)
if (mix.inProduction()) {
mix.version()
} else {
mix.browserSync({
proxy: 'http://localhost:80'
})
mix.options({
hmrOptions: {
host: 'localhost',
port: '8080',
},
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment