Boxed helps you actually know where your stuff is. Create boxes, drop items in, add photos, tag types, collaborators, mark packed status, search instantly - then ask BoxedAI “Where’s my winter jacket?” and get an answer sourced from your real inventory.
Think “Notion for your physical belongings” with an AI locator + packing coach. 🚀
Important
Born out of the frustration of moving & forgetting which box had that one cable. Now, Boxed keeps every item queryable & context‑aware, hehe. ✨
- About Boxed
- Core Features
- BoxedAI
- Tech Stack
- UI / UX Highlights
- Data Model
- Inventory Context Generation
- Getting Started
- Environment Variables
- Development Scripts
- CSV Export Format
- Docker & Containerization
- AWS & Terraform Deployment
- Testing
- Kubernetes Integration
- GitHub Actions CI/CD
- Makefile & Shell Scripts
- Secrets Scanning
- Contributing
- License
- Author
Boxed is a personal / household inventory & packing assistant built on top of Supabase (auth, Postgres, storage) + a modern Next.js frontend. It aims to eliminate: “Which box has the charger?”, “Did I already pack those mugs?”, “Where did I put winter clothes?”.
Use it while:
- Moving apartments
- Seasonal storage (winter vs. summer)
- Gear management (photography, hobby, tools)
- Shared spaces (roommates / family / team kit)
- College students managing dorm items (great when moving between semesters, or packing for breaks...)
All these features are designed to make the lives of movers, families, and especially college students easier, as I have been there myself - I often lost track of my belongings during moves and relocations, and I wish I had a tool like Boxed back then...
Boxed is built with a focus on simplicity, usability, and AI-powered assistance to help you find and pack your items efficiently.
You can try out Boxed live at boxed-app.vercel.app. Feel free to create an account and explore the features! 🚀
Boxed provides a comprehensive set of features to manage your home inventory and packing needs:
| Category | Features |
|---|---|
| Boxes | Create, rename inline, photo (upload/change/remove), set location, status (packed / unpacked), drag-to-reorder persistently |
| Items | Add per box, quantity, optional photo, type classification, edit inline via modal (name/qty/photo) |
| Types | Item types (e.g. Clothing, Cables, Kitchen) with pill color cycling |
| Collaborators | Share access (data model prepared with box_collaborators) |
| Search | Debounced global item search with box context + empty & loading states |
| Inline Editing | Box name & location directly editable (shadcn + custom EditableText) |
| Status Toggle | “Mark Packed / Mark Unpacked” pill-driven action |
| Photos | Box & item image storage via Supabase buckets |
| Export | One-click export of all boxes + items → CSV (flattened rows) |
| Responsive Nav | Collapses gracefully; spacing optimized for small screens |
| Tooltips | For destructive actions (e.g. remove photo) |
| Dark / Light | Theme toggle integrated with tokenized OKLCH palette |
| Persistence | Drag order per user stored in localStorage |
| Performance | Prompt-limited context generation, truncated lists for AI context |
| AI Assistant | BoxedAI chat bubble → inventory-aware retrieval & packing guidance |
| Accessibility | Keyboard navigation, focus management, aria labels for screen readers |
BoxedAI is our state-of-the-art, RAG-based AI assistant powered by Google AI. It helps you quickly locate items, suggest packing strategies, and answer questions about your inventory.
| Capability | Description |
|---|---|
| Item Locator | Ask it questions like: “Where is my HDMI cable?”, “Which box has ceramic mugs?” |
| Packing Tips | Suggests categorization, padding, consolidation ideas |
| Context Awareness | Receives summarized + truncated inventory (boxes + items + collaborators) |
| Clarification | If ambiguous or missing, asks follow-ups (instructed not to hallucinate) |
| Language Matching | Replies in same language as user input |
| Lightweight Session | Frontend builds history array & sends to the AI with carefulyl engineered system instruction |
Our AI assistant is prompt engineered to be fast, context-aware, and privacy-conscious. It only uses the inventory data you provide, ensuring your personal information remains secure.
Additionally, BoxedAI is powered by Retrieval-Augmented Generation (RAG), which means it can pull in relevant context from your inventory to provide accurate answers without hallucinating or making assumptions. This will help you find items quickly and efficiently, especially during stressful moving or packing situations!
Boxed is built with a modern stack that emphasizes performance, usability, and developer experience. Here’s a breakdown of the key technologies used:
| Layer | Stack |
|---|---|
| Frontend | Next.js (App/Pages hybrid depending), React 18, TypeScript |
| Styling | Tailwind CSS, shadcn/ui component primitives |
| State / UX | Local state hooks, dnd-kit for box reordering, dayjs for relative time |
| Backend (Managed) | Supabase: Auth, Postgres, Storage, Row-level queries |
| AI | Google Generative AI LLM |
| Validation | Zod schemas for box/item/type parsing |
| Icons | Lucide-react |
| MD Rendering | react-markdown + remark-gfm (chat responses) |
| Animations (select) | Framer Motion (earlier draggable variant) / CSS transitions |
| Build & Deploy | Vercel (web) + Supabase managed infra + AWS for optional fully-managed deployment + Ansible for automated deployment |
| Containerization | Docker for local dev + production images |
| CI/CD | GitHub Actions for automated testing, linting, and deployment |
| Testing | Jest for unit tests, Playwright/Cypress (planned) for E2E tests |
| Secrets Scanning | Trivy, GitHub Secrets Scanning, Yelp's secret scanning tools |
We focused on creating a clean, intuitive interface that makes managing your inventory a breeze. Here are some key UI/UX features:
- Inventory Dashboard: Drag re-order with handle hover (opacity reveal) - persists user order client-side.
- Box Hero Header: Gradient overlay + inline editable text + status pill + photo controls + tooltip for destructive photo removal.
- ItemCard: Photo / placeholder, quantity, relative “last used”, type pill, bottom-right edit pencil leading to modal.
- Box List: Infinite scroll with skeleton loading state, empty state, and search bar at the top.
- Item Search: Global search bar with debounced input, showing results across all boxes, with empty and loading states.
- Editable Text: Inline editing for box names and locations using shadcn EditableText component.
- Item Edit Modal: Name / quantity / photo choose → upload to bucket → optimistic closure.
- Chat Dialog: ScrollArea, Markdown bubbles, shift+enter newline, Enter send, inventory loading indicator.
- Export CSV: Flattened structure ready for spreadsheets or offline backup.
- Responsive Design: Mobile-first approach with collapsible navigation, optimized spacing, and touch-friendly controls.
- and so much more!
Boxed's user interface is designed to be intuitive and user-friendly, with a focus on simplicity and ease of use. Here are some key UI components:
Below is the core data model for Boxed, designed to be simple yet effective for managing boxes, items, and their relationships.
| Table | Key Fields | Notes |
|---|---|---|
profiles |
id (uuid PK), full_name, avatar_url |
Supabase auth metadata (implicit) |
boxes |
id uuid PK, owner_profile_id FK, name, location, status (packed/unpacked), photo_url, created_at |
Core container |
items |
id uuid PK, box_id FK, type_id FK?, name, quantity int, photo_url, last_used (timestamp), created_at |
Belongs to a box |
item_types |
id serial PK, name |
For classification pills |
box_collaborators |
box_id FK, collaborator_profile_id FK, role |
Multi-user future features |
(optional) activity_log |
id, actor_id, entity_type, entity_id, action, ts |
For future auditing |
Indexes you should have (recommended):
CREATE INDEX ON boxes (owner_profile_id);
CREATE INDEX ON items (box_id);
CREATE INDEX ON items (name text_pattern_ops);
CREATE INDEX ON items (type_id);
CREATE INDEX ON box_collaborators (box_id);Tip
Creating indexes will significantly speed up queries, especially for larger datasets. Use text_pattern_ops for case-insensitive searches on name.
Triggers you will want to add:
-- 1. Add the column(s) your trigger needs
ALTER TABLE public.profiles
ADD COLUMN IF NOT EXISTS email TEXT NOT NULL DEFAULT '',
ADD COLUMN IF NOT EXISTS full_name TEXT,
ADD COLUMN IF NOT EXISTS condition_tags TEXT[] DEFAULT ARRAY[]::text[],
ADD COLUMN IF NOT EXISTS created_at timestamptz DEFAULT now();
-- 2. Redefine your trigger to target public.profiles
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = 'public, auth'
AS $$
BEGIN
INSERT INTO public.profiles (
id,
email,
full_name,
condition_tags,
created_at
)
VALUES (
NEW.id,
NEW.email,
COALESCE(NEW.raw_user_meta_data ->> 'name', NEW.email),
ARRAY[]::text[],
now()
);
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW
EXECUTE PROCEDURE public.handle_new_user();Note
This trigger automatically creates a profile entry when a new user signs up via Supabase Auth. It uses the email and name from the auth metadata, defaulting to the email if no name is provided. It is very important to have this trigger in place to ensure that every user has a corresponding profile in the profiles table, which is essential for Boxed's functionality.
To support our AI assistant, we generate a context summary of the user's inventory and pass that via the RAG-method to the LLM to ensure the chatbot receives full context about the user's boxes and items. This is done client-side to minimize server load and latency.
-
Fetches all boxes owned by user.
-
Fetches all items for these boxes (batched).
-
Fetches collaborators (optional).
-
Truncates: max 30 boxes; max 25 items per box.
-
Produces summary lines like:
Box: "Kitchen Essentials" (id:abc) status:packed loc:Pantry items:5 => Plates (qty 8), Glasses (qty 6), ... -
Caches (via
localStorage) for 60s to avoid re-pulling on every chat open. -
Supplies to Google AI system instruction to ensure no hallucination, clarification if missing.
-
Uses
historyarray to maintain conversation context. -
Generates a truncated version of the inventory for the AI to use, ensuring it has enough context without overwhelming the model.
-
Uses
Zodschemas to validate the data structure before sending it to the AI.
This approach ensures that the AI assistant has a clear understanding of the user's inventory, allowing it to provide accurate and helpful responses without overwhelming the model with too much data.
To get started with Boxed, follow these simple steps:
git clone https://github.com/hoangsonww/Boxed-Inventory-App.git
cd Boxed-Inventory-App
# 1. Install deps
npm install
cd web
npm install
# 2. Env
cp .env.local.example .env.local
# Fill in: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_GOOGLE_AI_API_KEY
# 3. Run Dev
npm run dev
# -> http://localhost:3000
# 4. Supabase (if local)
# Use Supabase CLI (optional):
supabase start
# Alternatively, and recommended, use the hosted Supabase dashboard:
# Create a new project, copy the URL and anon key, and paste them into your .env.local
# Make sure to set up the database schema as per the Data Model section above.
# 5. Open in browser
# Open http://localhost:3000 in your browser to see Boxed in action!Tip
If you're using hosted Supabase dashboard, just paste URL + anon key in env file and skip local CLI.
As mentioned, Boxed requires some environment variables to function properly. Here’s a quick reference:
| Var | Required | Description |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
✅ | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
✅ | Public anon key |
NEXT_PUBLIC_GOOGLE_AI_API_KEY |
✅ | Google Gemini API key |
SUPABASE_SERVICE_ROLE_KEY |
❌ (server only) | For server-side maintenance tasks |
NEXT_PUBLIC_APP_NAME |
❌ | Branding override |
NEXT_PUBLIC_DEBUG_AI |
❌ | If 1, console logs AI context (dev only) |
Note
Some variables are only needed for server-side operations, like maintenance tasks or admin features. The NEXT_PUBLIC_ prefix indicates they are safe to expose to the client.
Warning
NEVER expose sensitive keys like SUPABASE_SERVICE_ROLE_KEY to the client-side code!!!!
Boxed comes with a set of convenient scripts to help you during development. Here’s a quick overview:
| Script | Purpose |
|---|---|
dev |
Run Next.js locally |
build |
Production build |
start |
Start production server |
lint |
ESLint (run from root directory) |
test |
Run Jest tests in the web directory |
test:watch |
Run Jest tests in watch mode (web) |
test:coverage |
Run Jest tests with coverage report (web) |
format |
Prettier write (run from root directory) |
Remember that you can only run lint or format from the root directory, as they are set up to lint/format both the web directory.
Each row contains a flattened view of boxes and items, allowing for easy import into spreadsheets or other tools. The CSV format is designed to be simple yet comprehensive.
| Column | Example |
|---|---|
box_id |
a8f9c8d1-... |
box_name |
Kitchen Essentials |
box_location |
Pantry |
box_status |
packed |
item_id |
f23f... or empty |
item_name |
Ceramic Mug |
item_quantity |
6 |
item_photo_url |
https://...supabase.../object |
Our CSV generation process is fully client-side (no server round trip), which uses Blob + URL.createObjectURL and reduces the need for server-side processing. This means you can export your inventory data quickly and easily, without any additional overhead.
Boxed can be containerized using Docker for easy deployment and scalability. We provide a Dockerfile and docker-compose.yml to help you get started quickly.
To build and run Boxed in a Docker container, follow these steps:
cd web
# build the image
docker build -t your-username/boxed-web .
# run it
docker run -p 3000:3000 your-username/boxed-webAlternatively, with docker-compose, you can run Boxed with a single command, from the root directory of the project:
docker-compose up --build -dThis will build the Docker image and start the Boxed web application on port 3000. You can then access it at http://localhost:3000.
Boxed can be deployed to AWS using Terraform for infrastructure management. This allows you to run Boxed on a fully managed stack with high availability and scalability.
To facilitate this, we provide a Terraform configuration that sets up the necessary AWS resources, including:
- VPC: For network isolation
- RDS: For PostgreSQL database
- S3: For static file storage
- IAM Roles: For secure access control
- CloudFront: For CDN distribution
- Route 53: For DNS management
- ECR: For container registry
- ECS: For container orchestration
This setup allows you to run Boxed in a production environment with minimal effort. You can find the Terraform configuration in the aws directory of the repository, and the AWS Deployment Guide provides detailed instructions on how to set up and deploy Boxed on AWS.
Boxed also includes optional Ansible playbooks for provisioning and managing the AWS infrastructure. These playbooks automate the setup of the necessary resources, making it easy to deploy Boxed on AWS.
To use the Ansible playbooks, you will need to have Ansible installed on your local machine. You can then run the playbooks to provision the AWS resources defined in the Terraform configuration.
We also have a deploy.sh script that automates the deployment process, including running the Terraform commands and applying the Ansible playbooks. For more details, checkout the ansible/ directory in the repository.
Boxed includes a comprehensive suite of tests to ensure reliability and correctness. We use Jest for unit and integration tests, with the following structure:
- Unit Tests: Cover individual components and functions.
- Integration Tests: Test interactions between components and the Supabase backend.
- E2E Tests: (planned) Use Playwright or Cypress to simulate user interactions and verify end-to-end functionality.
To run our existing Jest tests, simply execute:
cd web
npm run testAlternatively, you can run tests in watch mode for continuous feedback during development:
npm run test:watchOr, to generate a coverage report:
npm run test:coverageThis will run all tests and generate a coverage report in the coverage directory, which you can open in your browser to see which parts of the code are covered by tests.
Boxed can also be deployed on Kubernetes for those who prefer container orchestration. We provide a k8s directory with the necessary YAML files to deploy Boxed on a Kubernetes cluster.
This includes:
- Deployment: For the Boxed application
- Service: To expose the application
- Ingress: For routing traffic to the application
- ConfigMap: For environment variables and configuration
- Secret: For sensitive information like API keys
- PersistentVolumeClaim: For database storage
- HorizontalPodAutoscaler: For scaling the application based on load
- NetworkPolicy: For securing the application
- Resource Quotas: To limit resource usage
- and more...
For more details, check the kubernetes directory in the repository. This setup allows you to run Boxed in a highly available and scalable manner, leveraging the power of Kubernetes.
To ensure code quality and reliability, Boxed uses GitHub Actions for continuous integration and deployment. The CI/CD pipeline includes:
- Linting: Runs ESLint to check for code quality issues.
- Testing: Executes Jest tests to verify functionality.
- Build: Builds the Next.js application for production.
- Deployment: Deploys the application to Vercel or your chosen hosting provider.
- Docker Build: Builds the Docker image for Boxed and pushes it to the GH container registry.
- Vulnerability Scanning: Uses Trivy to scan the Docker image for vulnerabilities.
- and more...
You can find the GitHub Actions workflow files in the .github/workflows directory. These workflows are triggered on every push and pull request, ensuring that your code is always tested and ready for deployment.
To speed up your local development, infrastructure provisioning, and container workflow, Boxed provides a Makefile and a set of shell scripts under the scripts/ directory.
| Command | Description |
|---|---|
make build-image |
Build the Next.js app image (boxed-web:latest) from web/Dockerfile. |
make compose-up |
Start your local Docker Compose stack (docker-compose up --build -d). |
make compose-down |
Tear down the local Docker Compose stack. |
make infra-init |
Run terraform init in the aws/ directory to initialize your workspace. |
make infra-plan |
Run terraform plan -var="env=$(ENV)" to preview changes (defaults to dev). |
make infra-apply |
Apply your Terraform configuration (terraform apply -auto-approve). |
make infra-destroy |
Destroy all Terraform-managed resources (terraform destroy -auto-approve). |
You can override the environment by setting the ENV variable:
make infra-plan ENV=prodBoxed includes a few helper scripts in scripts/ for common tasks:
-
scripts/start-dev.sh
#!/usr/bin/env bash # Start Postgres, Supabase emulators, and frontend docker-compose -f docker-compose.dev.yml up -d postgres supabase cd web && npm install && npm run dev
Boots up your local Postgres & Supabase, then runs the Next.js dev server.
-
scripts/build-prod.sh
#!/usr/bin/env bash # Build production assets & Docker image cd web npm ci npm run build docker build --target runner -t boxed-web:prod -f Dockerfile .
Installs dependencies, builds the Next.js app, and produces the production image.
-
scripts/deploy-aws.sh
#!/usr/bin/env bash # Deploy the latest Terraform changes to AWS set -e cd aws terraform init terraform apply -auto-approve -var="env=${1:-dev}"
Applies your AWS infra changes. Pass an environment name (
dev,staging,prod) as the first argument.
Tip
Make all scripts executable with chmod +x scripts/*.sh and ensure you have the necessary AWS credentials and environment variables set.
To ensure the security of our Boxed project, we use a wide range of technologies and practices to scan for secrets and vulnerabilities in our codebase. This includes:
- Trivy: A powerful open-source vulnerability scanner that checks for known vulnerabilities in our Docker images and dependencies.
- GitHub Secrets Scanning: Automatically scans for sensitive information in our GitHub repositories, such as API keys, passwords, and other secrets.
- GitGuardian: A tool that helps detect and prevent the accidental exposure of sensitive information in our codebase.
- Pre-commit Hooks: We use pre-commit hooks to run automated checks before committing code, ensuring that no sensitive information is accidentally pushed to the repository.
- Yelp's Secret Scanning: We leverage Yelp's secret scanning tools to identify and remediate any potential security issues in our codebase, with a
.secrets.baselinefile to track known secrets. - GitHub Actions: Our CI/CD pipeline includes steps to run vulnerability scans and secret checks on every pull request, ensuring that any new code is thoroughly vetted before being merged.
- Code Reviews: We enforce strict code review practices to catch any potential security issues before they make it into the main branch.
Don't worry, we take security seriously and have implemented multiple layers of protection to keep your data safe. Our goal is to ensure that Boxed remains a secure and reliable tool for managing your home inventory!
- Fork the repository
- Create a new branch (
git checkout -b feature/your-feature) - Make your changes
- Run tests (
npm run test) and format code (npm run format) - Commit your changes (
git commit -m "Add your feature") - Push to your branch (
git push origin feature/your-feature) - Open a Pull Request
- Wait for review and address any feedback. We'll merge it if it meets our standards!
Important
For bug reports and feature suggestions → open an Issue with steps, expected, and actual behavior. For features, please include a clear description of the feature and how it would benefit users.
This project is licensed under the MIT License. Feel free to use, modify, and distribute it as you wish, but please keep the attribution intact.
Caution
You may not use this project for any commercial purposes without prior permission from the author. This includes using it as a base for a commercial product or service. You must also credit the original author in any derivative works, regardless of whether they are commercial or non-commercial.
Built with ☕ + chaotic moving experiences by Son Nguyen in 2025.
- GitHub: @hoangsonww
- LinkedIn: linkedin.com/in/hoangsonw
- Website: sonnguyenhoang.com
- Email: hoangson091104@gmail.com
Note
“Find. Pack. Ask. Relax.” 🐱
Boxed is your smart home inventory, packing, and retrieval assistant, designed to make moving and managing your belongings a breeze. Whether you're relocating, storing seasonal items, or just trying to keep track of your household gear, Boxed has you covered.
Enjoy never losing track of your stuff again. 🧳📦🧠












