Tools

Today's project

Run it. The reel stops on one project you can build today. Copy the prompt.

This page does not chat. Nothing is sent off this page. With JavaScript off, every project stays on the page with its prompt. The reel needs the script.

One run

The reel keeps scrolling, then stops on one project you can build.

Tools
  • Shelf, the bookshelf

    Read https://laravel-vuejs.space/laravel-soft-deletes-index-vue Build Shelf, a bookshelf for one reader. They add a book, mark it finished, and take it off the shelf. Screens: the shelf, one book, and a form to add a book. Models: Book with a title, a writer name, and a finished date. Call delete() from the button labeled Remove. Leave removed books off the shelf. Do not call forceDelete() from the button you labeled Remove. Do not pass removed books to the shelf and hide them with v-if. Show the diff. Do not commit.

    Keep soft-deleted rows off a Vue index
  • Standup, the daily board

    Read https://laravel-vuejs.space/laravel-policy-view-any-vue Build Standup, a board a team fills each morning. Each person posts what they did and what is next. Screens: today's board, one update, and a form to post yours. Models: Update with a person name, a did line, and a next line. Call authorize('viewAny', Update::class) before you list the morning. The gate answers whether this person may open the board. The query answers which rows. Do not filter the rows in Vue after sending every update. Show the diff. Do not commit.

    Gate a Vue index with viewAny
  • Field, the journal

    Read https://laravel-vuejs.space/laravel-vue-file-upload Build Field, a journal of site visits. Each visit has a note and a cover photo. Screens: the journal, one visit, and a form that adds the visit and its photo. Models: Visit with a place name, a note, and a cover path. Validate the photo as an image, max 2048 kilobytes. Post the form and send _method of put. Save the path. Do not put the file bytes in the database. PHP does not fill a file on a real PUT, PATCH, or DELETE. Show the diff. Do not commit.

    Upload files from Vue to Laravel with Inertia
  • Pantry, the kitchen list

    Read https://laravel-vuejs.space/laravel-vue-pagination Build Pantry, a list for one kitchen. Add an item, mark it used, and keep the list moving. Screens: the list, one item, and a form to add an item. Models: Item with a name, a spot in the kitchen, and a used date. Order the items by id and call cursorPaginate(10). A cursor page has no last_page. Do not order by a timestamp that can tie. Show the diff. Do not commit.

    Laravel and Vue pagination
  • Roster, the workshop list

    Read https://laravel-vuejs.space/laravel-breeze-jetstream-vue Build Roster, a list of people in a Saturday workshop. They sign in and then see who is coming. Screens: the login the kit already has, the roster, and a form to add your name. Models: Attendee with a name and a seat note. Use the login the Vue starter kit already ships. Do not install Breeze or Jetstream on top of the Vue starter kit. Show the diff. Do not commit.

    Breeze, Jetstream, and the Vue starter kit
  • Clip, the snippet box

    Read https://laravel-vuejs.space/pinia-laravel-inertia Build Clip, a box of short code notes for one person. Saved notes stay. A half-written note does not. Screens: the box, one note, and a form that holds the draft. Models: Snippet with a label and a body. Pass the saved snippets as a prop. Use Pinia only for a draft a refresh should forget. Do not router.reload the snippets into a Pinia store. Show the diff. Do not commit.

    When to use Pinia with Laravel and Inertia
  • Hours, the time log

    Read https://laravel-vuejs.space/laravel-migrate-on-deploy-vue Build Hours, a log of time one person spent on tasks. It does not send invoices and it does not take payment. Screens: the week, one entry, and a form to log minutes. Models: Entry with a task name, a day, and minutes. Run php artisan migrate --force in the release when you add the entries table. Do not call Artisan::call('migrate') from a controller. Do not migrate from a queued job. Show the diff. Do not commit.

    Run migrations in the release, not in a request
  • Relay, the announcement board

    Read https://laravel-vuejs.space/laravel-should-broadcast-vue Build Relay, an announcement board for one room. Post a note and the board updates for everyone there. Screens: the board, and a form to post a note. Models: Note with a body and an author name. Use ShouldBroadcast so the save does not wait on the socket. Leave broadcastOn on the public Channel. Listen with useEchoPublic. Do not listen with useEcho on a public channel. Do not put the provider key, or the Reverb secret, in the event payload. Show the diff. Do not commit.

    Queue a broadcast instead of blocking the save
  • Atlas, the trip log

    Read https://laravel-vuejs.space/laravel-eager-load-vue Build Atlas, a log of trips. Each stop names the person who wrote it. Screens: the trips, one trip with its stops, and a form to add a stop. Models: Trip, and Stop with a place name and an author. Call with('author') before you map the stops. Do not read the author inside map() after you forgot with(). Do not eager load every relation. Show the diff. Do not commit.

    Eager load a relation for a Vue list
  • Lane, the card board

    Read https://laravel-vuejs.space/laravel-queue-work-vs-listen Build Lane, a board of cards for one project. Columns are todo, doing, and done. Screens: the board, one card, and a form to add a card. Models: Card with a title, a column, and a note. Moving a card to done dispatches a job that records the move. Run queue:work in production and queue:listen on the laptop. Do not call queue:work from the controller. Show the diff. Do not commit.

    queue:work in production, listen locally
  • Press, the changelog

    Read https://laravel-vuejs.space/laravel-vue-flash Build Press, a public changelog for one product. A release note shows up on the list after you save it. Screens: the changelog, one note, and a form to publish a note. Models: Release with a version and a body. Return Inertia::flash('toast', ...) with the saved sentence. The starter kit already listens. Do not register a second router.on('flash'). Show the diff. Do not commit.

    Show a saved message in Vue
  • Plot, the garden log

    Read https://laravel-vuejs.space/simple-paginate-vue Build Plot, a log of beds in one garden. Each bed records what is planted. Screens: the beds, one bed, and a form to add a bed. Models: Bed with a name, a plant, and a planted date. Call simplePaginate on the beds. Render previous and next only. Do not print last_page or compute page 2 of undefined. Show the diff. Do not commit.

    Render simplePaginate without a last page
  • Crate, the moving list

    Read https://laravel-vuejs.space/laravel-soft-deletes-index-vue Build Crate, a list of boxes for one move. A box can come off the list and come back. Screens: the boxes, one box, and a form to add a box. Models: Box with a room name and a contents line. Call delete() from the button labeled Packed. Leave packed boxes off the open list. Do not call forceDelete() from the button you labeled Packed. Do not pass packed boxes to the open list and hide them with v-if. Show the diff. Do not commit.

    Keep soft-deleted rows off a Vue index
  • Table, the potluck board

    Read https://laravel-vuejs.space/inertia-preserve-state-vue Build Table, a board for one shared meal. People sign what dish they will bring, then sign out. Screens: the dishes, a form to claim a dish, and logout. Models: Dish with a name and the person who brings it. Post logout to the Fortify logout route. Keep preserveState only when a save still has errors. Do not set preserveState: true on a logout request. Show the diff. Do not commit.

    preserveState keeps the Vue page you have
  • Ink, the writing log

    Read https://laravel-vuejs.space/laravel-wayfinder-vue Build Ink, a log of drafts for one writer. Each draft has a title and a page count. Screens: the drafts, one draft, and a form to add a draft. Models: Draft with a title and a page count. Point the form at the generated controller action. This is not Vue Router. Inertia still navigates. Do not add vue-router beside it. Do not install Ziggy beside the generated functions. Show the diff. Do not commit.

    Typed Laravel routes in Vue with Wayfinder
  • Booth, the event album

    Read https://laravel-vuejs.space/laravel-vue-file-upload Build Booth, an album for one event. Each photo has a caption. Screens: the album, one photo, and a form that adds the photo. Models: Photo with a caption and a path. Validate the photo as an image, max 2048 kilobytes. Post the form and send _method of put. Save the path. Do not put the file bytes in the database. PHP does not fill a file on a real PUT, PATCH, or DELETE. Show the diff. Do not commit.

    Upload files from Vue to Laravel with Inertia
  • Desk, the bug list

    Read https://laravel-vuejs.space/laravel-vue-pagination Build Desk, a list of bugs for one app. Open a bug, write what happened, and mark it fixed. Screens: the list, one bug, and a form to report a bug. Models: Bug with a title, a report, and a fixed date. Order the bugs by id and call cursorPaginate(10). A cursor page has no last_page. Do not order by a timestamp that can tie. Show the diff. Do not commit.

    Laravel and Vue pagination
  • Issue, the small magazine

    Read https://laravel-vuejs.space/inertia-ssr-process-cloud Build a small magazine one editor publishes. A reader opens the public list of pieces. Screens: the public list, one piece, and a form to publish a piece. Models: Piece with a title, a body, and a published date. Supervise one SSR process for that public list. Do not read window in setup. Do not start a second SSR process on another port. Show the diff. Do not commit.

    Keep the Inertia SSR process running
  • Shift, the weekly rota

    Read https://laravel-vuejs.space/laravel-policy-view-any-vue Build Shift, a rota for one cafe week. Staff see the shifts they are allowed to open. Screens: the week, one shift, and a form to add a shift. Models: ShiftSlot with a day, a start time, and a person name. Call authorize('viewAny', ShiftSlot::class) before you list the week. The gate answers whether this person may open the rota. The query answers which rows. Do not filter the rows in Vue after sending every shift. Show the diff. Do not commit.

    Gate a Vue index with viewAny
  • Borrow, the tool library

    Read https://laravel-vuejs.space/laravel-vue-flash Build a library of tools neighbors lend. A person marks a tool out and later marks it back. Screens: the tools, one tool, and a form to add a tool. Models: Tool with a name, an owner name, and a due date. Return Inertia::flash('toast', ...) when a tool is marked out. The starter kit already listens. Do not register a second router.on('flash'). Show the diff. Do not commit.

    Show a saved message in Vue
  • Menu, the dinner plan

    Read https://laravel-vuejs.space/pinia-laravel-inertia Build Menu, a week of dinners for one home. Saved meals stay. A meal you have not saved does not. Screens: the week, one dinner, and a form that holds the unsaved meal. Models: Dinner with a day and a dish name. Pass the saved dinners as a prop. Use Pinia only for a draft a refresh should forget. Do not router.reload the dinners into a Pinia store. Show the diff. Do not commit.

    When to use Pinia with Laravel and Inertia
  • Streak, the practice log

    Read https://laravel-vuejs.space/laravel-wayfinder-vue Build Streak, a log of practice days for one person. Each day records what they practiced. Screens: the days, one day, and a form to log a day. Models: Practice with a day and a note. Point the form at the generated controller action. This is not Vue Router. Inertia still navigates. Do not add vue-router beside it. Do not install Ziggy beside the generated functions. Show the diff. Do not commit.

    Typed Laravel routes in Vue with Wayfinder